This commit is contained in:
zandercymatics 2024-09-24 14:22:25 -06:00
parent f9e60ac237
commit 61b1ceeb9c
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
16 changed files with 435 additions and 138 deletions

View file

@ -21,7 +21,12 @@ from epplibwrapper.errors import ErrorCode, RegistryError
from registrar.models.user_domain_role import UserDomainRole
from waffle.admin import FlagAdmin
from waffle.models import Sample, Switch
from registrar.utility.admin_helpers import get_all_action_needed_reason_emails, get_action_needed_reason_default_email
from registrar.utility.admin_helpers import (
get_all_action_needed_reason_emails,
get_action_needed_reason_default_email,
get_all_rejection_reason_emails,
get_rejection_reason_default_email,
)
from registrar.models import Contact, Domain, DomainRequest, DraftDomain, User, Website, SeniorOfficial
from registrar.utility.constants import BranchChoices
from registrar.utility.errors import FSMDomainRequestError, FSMErrorCodes
@ -234,6 +239,7 @@ class DomainRequestAdminForm(forms.ModelForm):
}
labels = {
"action_needed_reason_email": "Email",
"rejection_reason_email": "Email",
}
def __init__(self, *args, **kwargs):
@ -1755,6 +1761,7 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
"status_history",
"status",
"rejection_reason",
"rejection_reason_email",
"action_needed_reason",
"action_needed_reason_email",
"investigator",
@ -1938,24 +1945,16 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
original_obj = models.DomainRequest.objects.get(pk=obj.pk)
# == Handle action_needed_reason == #
action_needed_reason_changed = obj.action_needed_reason != original_obj.action_needed_reason
if action_needed_reason_changed:
obj = self._handle_action_needed_reason(request, obj, original_obj)
reason_changed = obj.action_needed_reason != original_obj.action_needed_reason
if reason_changed:
# Track the fact that we sent out an email
request.session["action_needed_email_sent"] = True
# Set the action_needed_reason_email to the default if nothing exists.
# Since this check occurs after save, if the user enters a value then we won't update.
default_email = get_action_needed_reason_default_email(request, obj, obj.action_needed_reason)
if obj.action_needed_reason_email:
emails = get_all_action_needed_reason_emails(request, obj)
is_custom_email = obj.action_needed_reason_email not in emails.values()
if not is_custom_email:
obj.action_needed_reason_email = default_email
else:
obj.action_needed_reason_email = default_email
# == Handle rejection_reason == #
rejection_reason_changed = obj.rejection_reason != original_obj.rejection_reason
if rejection_reason_changed:
obj = self._handle_rejection_reason(request, obj, original_obj)
# == Handle allowed emails == #
if obj.status in DomainRequest.get_statuses_that_send_emails() and not settings.IS_PRODUCTION:
self._check_for_valid_email(request, obj)
@ -1971,6 +1970,40 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
if should_save:
return super().save_model(request, obj, form, change)
def _handle_action_needed_reason(self, request, obj, original_obj):
# Track the fact that we sent out an email
request.session["action_needed_email_sent"] = True
# Set the action_needed_reason_email to the default if nothing exists.
# Since this check occurs after save, if the user enters a value then we won't update.
default_email = get_action_needed_reason_default_email(obj, obj.action_needed_reason)
if obj.action_needed_reason_email:
emails = get_all_action_needed_reason_emails(obj)
is_custom_email = obj.action_needed_reason_email not in emails.values()
if not is_custom_email:
obj.action_needed_reason_email = default_email
else:
obj.action_needed_reason_email = default_email
return obj
def _handle_rejection_reason(self, request, obj, original_obj):
# Track the fact that we sent out an email
request.session["rejection_reason_email_sent"] = True
# Set the rejection_reason_email to the default if nothing exists.
# Since this check occurs after save, if the user enters a value then we won't update.
default_email = get_rejection_reason_default_email(obj, obj.action_needed_reason)
if obj.rejection_reason_email:
emails = get_all_rejection_reason_emails(obj)
is_custom_email = obj.rejection_reason_email not in emails.values()
if not is_custom_email:
obj.rejection_reason_email = default_email
else:
obj.rejection_reason_email = default_email
return obj
def _check_for_valid_email(self, request, obj):
"""Certain emails are whitelisted in non-production environments,
so we should display that information using this function.

View file

@ -500,83 +500,41 @@ function initializeWidgetOnList(list, parentId) {
}
})();
class CustomizableEmailBase {
constructor(dropdown, textarea, textareaPlaceholder, directEditButton, modalTrigger, modalConfirm, formLabel, lastSentEmailContent, apiUrl) {
this.dropdown = dropdown;
this.textarea = textarea;
this.textareaPlaceholder = textareaPlaceholder;
this.directEditButton = directEditButton;
this.modalTrigger = modalTrigger;
this.modalConfirm = modalConfirm;
this.formLabel = formLabel;
this.lastSentEmailContent = lastSentEmailContent;
this.apiUrl = apiUrl;
/** An IIFE that hooks to the show/hide button underneath action needed reason.
* This shows the auto generated email on action needed reason.
*/
document.addEventListener('DOMContentLoaded', function() {
const dropdown = document.getElementById("id_action_needed_reason");
const textarea = document.getElementById("id_action_needed_reason_email")
const domainRequestId = dropdown ? document.getElementById("domain_request_id").value : null
const textareaPlaceholder = document.querySelector(".field-action_needed_reason_email__placeholder");
const directEditButton = document.querySelector('.field-action_needed_reason_email__edit');
const modalTrigger = document.querySelector('.field-action_needed_reason_email__modal-trigger');
const modalConfirm = document.getElementById('confirm-edit-email');
const formLabel = document.querySelector('label[for="id_action_needed_reason_email"]');
let lastSentEmailContent = document.getElementById("last-sent-email-content");
const initialDropdownValue = dropdown ? dropdown.value : null;
const initialEmailValue = textarea.value;
this.domainRequestId = this.dropdown ? document.getElementById("domain_request_id").value : null
this.initialDropdownValue = this.dropdown ? this.dropdown.value : null;
this.initialEmailValue = this.textarea ? this.textarea.value : null;
// We will use the const to control the modal
let isEmailAlreadySentConst = lastSentEmailContent.value.replace(/\s+/g, '') === textarea.value.replace(/\s+/g, '');
// We will use the function to control the label and help
function isEmailAlreadySent() {
return lastSentEmailContent.value.replace(/\s+/g, '') === textarea.value.replace(/\s+/g, '');
}
if (!dropdown || !textarea || !domainRequestId || !formLabel || !modalConfirm) return;
const apiUrl = document.getElementById("get-action-needed-email-for-user-json").value;
function updateUserInterface(reason) {
if (!reason) {
// No reason selected, we will set the label to "Email", show the "Make a selection" placeholder, hide the trigger, textarea, hide the help text
formLabel.innerHTML = "Email:";
textareaPlaceholder.innerHTML = "Select an action needed reason to see email";
showElement(textareaPlaceholder);
hideElement(directEditButton);
hideElement(modalTrigger);
hideElement(textarea);
} else if (reason === 'other') {
// 'Other' selected, we will set the label to "Email", show the "No email will be sent" placeholder, hide the trigger, textarea, hide the help text
formLabel.innerHTML = "Email:";
textareaPlaceholder.innerHTML = "No email will be sent";
showElement(textareaPlaceholder);
hideElement(directEditButton);
hideElement(modalTrigger);
hideElement(textarea);
} else {
// A triggering selection is selected, all hands on board:
textarea.setAttribute('readonly', true);
showElement(textarea);
hideElement(textareaPlaceholder);
if (isEmailAlreadySentConst) {
hideElement(directEditButton);
showElement(modalTrigger);
} else {
showElement(directEditButton);
hideElement(modalTrigger);
}
if (isEmailAlreadySent()) {
formLabel.innerHTML = "Email sent to creator:";
} else {
formLabel.innerHTML = "Email:";
}
this.isEmailAlreadySentConst;
if (lastSentEmailContent && textarea) {
this.isEmailAlreadySentConst = lastSentEmailContent.value.replace(/\s+/g, '') === textarea.value.replace(/\s+/g, '');
}
}
// Initialize UI
updateUserInterface(dropdown.value);
dropdown.addEventListener("change", function() {
const reason = dropdown.value;
// Update the UI
updateUserInterface(reason);
if (reason && reason !== "other") {
// If it's not the initial value
if (initialDropdownValue !== dropdown.value || initialEmailValue !== textarea.value) {
initializeDropdown(errorMessage) {
this.dropdown.addEventListener("change", () => {
console.log(this.dropdown)
let reason = this.dropdown.value;
if (this.initialDropdownValue !== this.dropdown.value || this.initialEmailValue !== this.textarea.value) {
let searchParams = new URLSearchParams(
{
"reason": reason,
"domain_request_id": this.domainRequestId,
}
);
// Replace the email content
fetch(`${apiUrl}?reason=${reason}&domain_request_id=${domainRequestId}`)
fetch(`${this.apiUrl}?${searchParams.toString()}`)
.then(response => {
return response.json().then(data => data);
})
@ -584,30 +542,174 @@ document.addEventListener('DOMContentLoaded', function() {
if (data.error) {
console.error("Error in AJAX call: " + data.error);
}else {
textarea.value = data.action_needed_email;
this.textarea.value = data.action_needed_email;
}
updateUserInterface(reason);
this.updateUserInterface(reason);
})
.catch(error => {
console.error("Error action needed email: ", error)
console.error(errorMessage, error)
});
}
});
}
initializeModalConfirm() {
this.modalConfirm.addEventListener("click", () => {
this.textarea.removeAttribute('readonly');
this.textarea.focus();
hideElement(this.directEditButton);
hideElement(this.modalTrigger);
});
}
initializeDirectEditButton() {
this.directEditButton.addEventListener("click", () => {
this.textarea.removeAttribute('readonly');
this.textarea.focus();
hideElement(this.directEditButton);
hideElement(this.modalTrigger);
});
}
isEmailAlreadySent() {
return this.lastSentEmailContent.value.replace(/\s+/g, '') === this.textarea.value.replace(/\s+/g, '');
}
updateUserInterface(reason) {
if (!reason) {
// No reason selected, we will set the label to "Email", show the "Make a selection" placeholder, hide the trigger, textarea, hide the help text
this.showPlaceholder("Email:", "Select an action needed reason to see email");
} else if (reason === 'other') {
// 'Other' selected, we will set the label to "Email", show the "No email will be sent" placeholder, hide the trigger, textarea, hide the help text
this.showPlaceholder("Email:", "No email will be sent");
} else {
// A triggering selection is selected, all hands on board:
this.textarea.setAttribute('readonly', true);
showElement(this.textarea);
hideElement(this.textareaPlaceholder);
if (this.isEmailAlreadySentConst) {
hideElement(this.directEditButton);
showElement(this.modalTrigger);
} else {
showElement(this.directEditButton);
hideElement(this.modalTrigger);
}
if (this.isEmailAlreadySent()) {
this.formLabel.innerHTML = "Email sent to creator:";
} else {
this.formLabel.innerHTML = "Email:";
}
}
}
});
showPlaceholder(formLabelText, placeholderText) {
this.formLabel.innerHTML = formLabelText;
this.textareaPlaceholder.innerHTML = placeholderText;
showElement(this.textareaPlaceholder);
hideElement(this.directEditButton);
hideElement(this.modalTrigger);
hideElement(this.textarea);
}
}
modalConfirm.addEventListener("click", () => {
textarea.removeAttribute('readonly');
textarea.focus();
hideElement(directEditButton);
hideElement(modalTrigger);
});
directEditButton.addEventListener("click", () => {
textarea.removeAttribute('readonly');
textarea.focus();
hideElement(directEditButton);
hideElement(modalTrigger);
});
class customActionNeededEmail extends CustomizableEmailBase {
constructor() {
const dropdown = document.getElementById("id_action_needed_reason");
const textarea = document.getElementById("id_action_needed_reason_email")
const textareaPlaceholder = document.querySelector(".field-action_needed_reason_email__placeholder");
const directEditButton = document.querySelector('.field-action_needed_reason_email__edit');
const modalTrigger = document.querySelector('.field-action_needed_reason_email__modal-trigger');
const modalConfirm = document.getElementById('confirm-edit-email');
const formLabel = document.querySelector('label[for="id_action_needed_reason_email"]');
const lastSentEmailContent = document.getElementById("last-sent-email-content");
let apiContainer = document.getElementById("get-action-needed-email-for-user-json")
const apiUrl = apiContainer ? apiContainer.value : null;
super(
dropdown,
textarea,
textareaPlaceholder,
directEditButton,
modalTrigger,
modalConfirm,
formLabel,
lastSentEmailContent,
apiUrl
);
}
loadActionNeededEmail() {
this.updateUserInterface(this.dropdown.value);
this.initializeDropdown("Error when attempting to grab action needed email: ")
this.initializeModalConfirm()
this.initializeDirectEditButton()
}
}
/** An IIFE that hooks to the show/hide button underneath action needed reason.
* This shows the auto generated email on action needed reason.
*/
document.addEventListener('DOMContentLoaded', function() {
const customEmail = new customActionNeededEmail();
if (!customEmail.dropdown || !customEmail.textarea || !customEmail.domainRequestId || !customEmail.formLabel || !customEmail.modalConfirm){
return;
}
// Initialize UI
customEmail.loadActionNeededEmail()
});
class customRejectedEmail extends CustomizableEmailBase {
constructor() {
const dropdown = document.getElementById("id_rejection_reason");
const textarea = document.getElementById("id_rejection_reason_email")
const textareaPlaceholder = document.querySelector(".field-rejection_reason_email__placeholder");
const directEditButton = document.querySelector('.field-rejection_reason_email__edit');
const modalTrigger = document.querySelector('.field-rejection_reason_email__modal-trigger');
const modalConfirm = document.getElementById('confirm-edit-email');
const formLabel = document.querySelector('label[for="id_rejection_reason_email"]');
const lastSentEmailContent = document.getElementById("last-sent-email-content");
let apiContainer = document.getElementById("get-rejection-reason-email-for-user-json")
const apiUrl = apiContainer ? apiContainer.value : null;
super(
dropdown,
textarea,
textareaPlaceholder,
directEditButton,
modalTrigger,
modalConfirm,
formLabel,
lastSentEmailContent,
apiUrl
);
}
loadRejectedEmail() {
this.updateUserInterface(this.dropdown.value);
this.initializeDropdown("Error when attempting to grab rejected email: ")
this.initializeModalConfirm()
this.initializeDirectEditButton()
}
}
/** An IIFE that hooks to the show/hide button underneath rejected reason.
* This shows the auto generated email on action needed reason.
*/
document.addEventListener('DOMContentLoaded', function() {
const customEmail = new customRejectedEmail();
if (!customEmail.dropdown || !customEmail.textarea || !customEmail.domainRequestId || !customEmail.formLabel || !customEmail.modalConfirm){
return;
}
// Initialize UI
customEmail.loadRejectedEmail()
});

View file

@ -300,6 +300,11 @@ class DomainRequest(TimeStampedModel):
blank=True,
)
rejection_reason_email = models.TextField(
null=True,
blank=True,
)
action_needed_reason = models.TextField(
choices=ActionNeededReasons.choices,
null=True,
@ -798,6 +803,21 @@ class DomainRequest(TimeStampedModel):
except EmailSendingError:
logger.warning("Failed to send confirmation email", exc_info=True)
def _send_custom_status_update_email(self, email_content):
"""Wrapper for `_send_status_update_email` that bcc's help@get.gov
and sends an email equivalent to the 'email_content' variable."""
if settings.IS_PRODUCTION:
bcc_address = settings.DEFAULT_FROM_EMAIL
self._send_status_update_email(
new_status="action needed",
email_template=f"emails/includes/custom_email.txt",
email_template_subject=f"emails/status_change_subject.txt",
bcc_address=bcc_address,
custom_email_content=email_content,
wrap_email=True,
)
def investigator_exists_and_is_staff(self):
"""Checks if the current investigator is in a valid state for a state transition"""
is_valid = True
@ -901,7 +921,7 @@ class DomainRequest(TimeStampedModel):
target=DomainRequestStatus.ACTION_NEEDED,
conditions=[domain_is_not_active, investigator_exists_and_is_staff],
)
def action_needed(self, send_email=True):
def action_needed(self):
"""Send back an domain request that is under investigation or rejected.
This action is logged.
@ -924,27 +944,7 @@ class DomainRequest(TimeStampedModel):
# Send out an email if an action needed reason exists
if self.action_needed_reason and self.action_needed_reason != self.ActionNeededReasons.OTHER:
email_content = self.action_needed_reason_email
self._send_action_needed_reason_email(send_email, email_content)
def _send_action_needed_reason_email(self, send_email=True, email_content=None):
"""Sends out an automatic email for each valid action needed reason provided"""
email_template_name = "custom_email.txt"
email_template_subject_name = f"{self.action_needed_reason}_subject.txt"
bcc_address = ""
if settings.IS_PRODUCTION:
bcc_address = settings.DEFAULT_FROM_EMAIL
self._send_status_update_email(
new_status="action needed",
email_template=f"emails/action_needed_reasons/{email_template_name}",
email_template_subject=f"emails/action_needed_reasons/{email_template_subject_name}",
send_email=send_email,
bcc_address=bcc_address,
custom_email_content=email_content,
wrap_email=True,
)
self._send_custom_status_update_email(email_content)
@transition(
field="status",
@ -1051,6 +1051,11 @@ class DomainRequest(TimeStampedModel):
"emails/status_change_rejected_subject.txt",
)
# Send out an email if a rejection reason exists
if self.rejection_reason:
email_content = self.rejection_reason_email
self._send_custom_status_update_email(email_content)
@transition(
field="status",
source=[

View file

@ -0,0 +1,10 @@
THANK YOU
.Gov helps the public identify official, trusted information. Thank you for requesting a .gov domain.
----------------------------------------------------------------
The .gov team
Contact us: <https://get.gov/contact/>
Learn about .gov <https://get.gov>
The .gov registry is a part of the Cybersecurity and Infrastructure Security Agency (CISA) <https://cisa.gov/>

View file

@ -0,0 +1,8 @@
Hi, {{ recipient.first_name }}.
Your .gov domain request has been rejected.
DOMAIN REQUESTED: {{ domain_request.requested_domain.name }}
REQUEST RECEIVED ON: {{ domain_request.last_submitted_date|date }}
STATUS: Rejected
----------------------------------------------------------------

View file

@ -0,0 +1,8 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
{% include "emails/includes/status_change_rejected_header.html" %}
REJECTION REASON
Your domain request was rejected because we could not verify the organizational
contacts you provided. If you have questions or comments, reply to this email.
{% include "emails/includes/email_footer.html" %}
{% endautoescape %}

View file

@ -0,0 +1,15 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
{% include "emails/includes/status_change_rejected_header.html" %}
REJECTION REASON
Your domain request was rejected because it does not meet our naming requirements.
Domains should uniquely identify a government organization and be clear to the
general public. Learn more about naming requirements for your type of organization
<https://get.gov/domains/choosing/>.
YOU CAN SUBMIT A NEW REQUEST
We encourage you to request a domain that meets our requirements. If you have
questions or want to discuss potential domain names, reply to this email.
{% include "emails/includes/email_footer.html" %}
{% endautoescape %}

View file

@ -0,0 +1,15 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
{% include "emails/includes/status_change_rejected_header.html" %}
REJECTION REASON
Your domain request was rejected because {{ domain_request.organization_name }} has a .gov domain. Our
practice is to approve one domain per online service per government organization. We
evaluate additional requests on a case-by-case basis. You did not provide sufficient
justification for an additional domain.
Read more about our practice of approving one domain per online service
<https://get.gov/domains/before/#one-domain-per-service>.
If you have questions or comments, reply to this email.
{% include "emails/includes/email_footer.html" %}
{% endautoescape %}

View file

@ -0,0 +1,14 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
{% include "emails/includes/status_change_rejected_header.html" %}
REJECTION REASON
Your domain request was rejected because we determined that {{ domain_request.organization_name }} is not
eligible for a .gov domain. .Gov domains are only available to official U.S.-based
government organizations.
Learn more about eligibility for .gov domains
<https://get.gov/domains/eligibility/>.
If you have questions or comments, reply to this email.
{% include "emails/includes/email_footer.html" %}
{% endautoescape %}

View file

@ -0,0 +1,15 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
{% include "emails/includes/status_change_rejected_header.html" %}
YOU CAN SUBMIT A NEW REQUEST
If your organization is eligible for a .gov domain and you meet our other requirements, you can submit a new request.
Learn more about:
- Eligibility for a .gov domain <https://get.gov/domains/eligibility>
- Choosing a .gov domain name <https://get.gov/domains/choosing>
NEED ASSISTANCE?
If you have questions about this domain request or need help choosing a new domain name, reply to this email.
{% include "emails/includes/email_footer.html" %}
{% endautoescape %}

View file

@ -0,0 +1,15 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
{% include "emails/includes/status_change_rejected_header.html" %}
REJECTION REASON
Your domain request was rejected because the purpose you provided did not meet our
requirements. You didnt provide enough information about how you intend to use the
domain.
Learn more about:
- Eligibility for a .gov domain <https://get.gov/domains/eligibility>
- What you can and cant do with .gov domains <https://get.gov/domains/requirements/>
If you have questions or comments, reply to this email.
{% include "emails/includes/email_footer.html" %}
{% endautoescape %}

View file

@ -0,0 +1,14 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
{% include "emails/includes/status_change_rejected_header.html" %}
REJECTION REASON
Your domain request was rejected because we dont believe youre eligible to request a
.gov domain on behalf of {{ domain_request.organization_name }}. You must be a government employee, or be
working on behalf of a government organization, to request a .gov domain.
DEMONSTRATE ELIGIBILITY
If you can provide more information that demonstrates your eligibility, or you want to
discuss further, reply to this email.
{% include "emails/includes/email_footer.html" %}
{% endautoescape %}

View file

@ -2,23 +2,66 @@ from registrar.models.domain_request import DomainRequest
from django.template.loader import get_template
def get_all_action_needed_reason_emails(request, domain_request):
def get_all_action_needed_reason_emails(domain_request):
"""Returns a dictionary of every action needed reason and its associated email
for this particular domain request."""
return _get_all_default_emails(
reasons=DomainRequest.ActionNeededReasons,
# Where the emails are stored. This assumes that it contains a list of .txt files with the reason.
path_root="emails/action_needed_reasons",
# What reasons don't send out emails (none is handled automagically)
excluded_reasons=[DomainRequest.ActionNeededReasons.OTHER],
# Who to send it to, and from what domain request to reference
domain_request=domain_request
)
def get_action_needed_reason_default_email(domain_request, action_needed_reason):
"""Returns the default email associated with the given action needed reason"""
return _get_default_email(
domain_request,
path_root="emails/rejection_reasons",
reason=action_needed_reason,
excluded_reasons=[DomainRequest.ActionNeededReasons.OTHER]
)
def get_all_rejection_reason_emails(domain_request):
"""Returns a dictionary of every rejection reason and its associated email
for this particular domain request."""
return _get_all_default_emails(
reasons=DomainRequest.RejectionReasons,
# Where the emails are stored. This assumes that it contains a list of .txt files with the reason.
path_root="emails/rejection_reasons",
# What reasons don't send out emails (none is handled automagically)
excluded_reasons=[DomainRequest.RejectionReasons.OTHER],
# Who to send it to, and from what domain request to reference
domain_request=domain_request
)
def get_rejection_reason_default_email(domain_request, action_needed_reason):
"""Returns the default email associated with the given rejection reason"""
return _get_default_email(
domain_request,
path_root="emails/rejection_reasons",
reason=action_needed_reason,
excluded_reasons=[DomainRequest.RejectionReasons.OTHER]
)
def _get_all_default_emails(reasons, path_root, excluded_reasons, domain_request):
emails = {}
for action_needed_reason in domain_request.ActionNeededReasons:
# Map the action_needed_reason to its default email
emails[action_needed_reason.value] = get_action_needed_reason_default_email(
request, domain_request, action_needed_reason.value
for reason in reasons:
# Map the reason to its default email
emails[reason.value] = _get_default_email(
domain_request, path_root, reason, excluded_reasons
)
return emails
def _get_default_email(domain_request, path_root, reason, excluded_reasons=None):
if not reason:
return None
def get_action_needed_reason_default_email(request, domain_request, action_needed_reason):
"""Returns the default email associated with the given action needed reason"""
if not action_needed_reason or action_needed_reason == DomainRequest.ActionNeededReasons.OTHER:
if excluded_reasons and reason in excluded_reasons:
return None
recipient = domain_request.creator
@ -26,7 +69,7 @@ def get_action_needed_reason_default_email(request, domain_request, action_neede
context = {"domain_request": domain_request, "recipient": recipient}
# Get the email body
template_path = f"emails/action_needed_reasons/{action_needed_reason}.txt"
template_path = f"{path_root}/{reason}.txt"
email_body_text = get_template(template_path).render(context=context)
email_body_text_cleaned = None

View file

@ -90,5 +90,5 @@ def get_action_needed_email_for_user_json(request):
return JsonResponse({"error": "No domain_request_id specified"}, status=404)
domain_request = DomainRequest.objects.filter(id=domain_request_id).first()
emails = get_all_action_needed_reason_emails(request, domain_request)
emails = get_all_action_needed_reason_emails(domain_request)
return JsonResponse({"action_needed_email": emails.get(reason)}, status=200)