Hi>
I am trying to make a custom email button on frappe using Client and server Script Doctypes but i am not able to and i am not even able to figure out why? Can someone help me out:
Client Script:
frappe.ui.form.on(‘Donation’, {
refresh: function(frm) {
// Only show the button for saved documents
if (!frm.is_new() && !frm.doc.__islocal) {
// Determine the recipient email address
let recipient_email = '';
if (frm.doc.receipt_donor_email) {
recipient_email = frm.doc.receipt_donor_email;
} else if (frm.doc.donor_email) {
recipient_email = frm.doc.donor_email;
}
// Clear existing button first to avoid duplicates on refresh
frm.remove_custom_button(__('Send Receipt Email'));
// Add the button only if an email address is potentially available
// (We do the final check inside the click handler)
if (frm.doc.receipt_donor_email || frm.doc.donor_email) {
frm.add_custom_button(__('Send Receipt Email'), function() {
// Re-check the email address at the time of click
let current_recipient_email = '';
if (frm.doc.receipt_donor_email) {
current_recipient_email = frm.doc.receipt_donor_email;
} else if (frm.doc.donor_email) {
current_recipient_email = frm.doc.donor_email;
}
if (!current_recipient_email) {
frappe.msgprint({
title: __('Cannot Send Email'),
indicator: 'orange',
message: __('No donor email found in "Receipt Donor Email" or "Donor Email" fields.')
});
return; // Stop execution
}
frappe.confirm(
__('Send donation receipt email to {0}?', [current_recipient_email]),
function() { // User confirms (yes callback)
// Show progress
frappe.show_alert({ message: __('Sending Email...'), indicator: 'blue' });
// Call the server script (API)
frappe.call({
method: 'send-donation-receipt-email', // Use 'Server Script Name/ID'.'Method Name'
args: {
doctype: frm.doc.doctype, // Pass the DocType name
doc_name: frm.doc.name, // Pass the document ID/name
recipient_email: current_recipient_email // Pass the determined recipient
},
callback: function(response) {
// Callback is executed on successful *server method execution*
// The server script itself uses frappe.msgprint for success feedback
// You could add more client-side feedback here if needed based on response.message
// e.g., if (response.message && response.message.status === 'success') { ... }
// frappe.hide_progress(); // Not needed if using show_alert
},
error: function(error) {
// Error is executed if the server call fails OR if the server script throws an exception
// frappe.hide_progress();
// The server script already logs the error, just show a message to the user
// Error message is usually in error.message
frappe.msgprint({
title: __('Error Sending Email'),
indicator: 'red',
message: error.message || __('An unknown error occurred while trying to send the email.')
});
},
always: function() {
// Runs after callback or error
// You might want to disable the button briefly after click here
console.log("Email sending attempt finished.");
}
});
},
function() { // User cancels (no callback)
// Optional: Add a message if the user cancels
// frappe.msgprint(__('Email sending cancelled.'));
}
);
}).addClass('btn-primary'); // Optional: Make the button blue
} else {
// Optional: If you want to explicitly show *why* the button isn't there
// console.log("Send Receipt Email button not added: No donor email address found.");
}
} else {
// Optional: Clear button if form becomes new (e.g., user clicks New after viewing a record)
frm.remove_custom_button(__('Send Receipt Email'));
}
}
});
ServerScript:
def send_email(doc_name, recipient_email, doctype):
try:
# Basic check for recipient email format (optional, frappe.sendmail also checks)
if not recipient_email or "@" not in recipient_email:
frappe.throw(f"Invalid or missing recipient email address: {recipient_email}")
# Get the document
doc = frappe.get_doc(doctype, doc_name)
# --- Customize Email Content ---
subject = f"Thank You for Your Donation - {doc.name}"
# Attempt to use utility functions via the frappe object
try:
# Assuming doc.amount exists
amount = doc.get("amount", 0) # Use .get for safety
currency = doc.get("currency") or frappe.db.get_default("currency") or "USD"
formatted_amount = frappe.utils.fmt_money(amount, currency=currency)
except AttributeError:
# Fallback if frappe.utils.fmt_money is somehow still restricted/unavailable
frappe.log_error("frappe.utils.fmt_money not accessible in server script")
formatted_amount = f"{amount} {currency}"
except Exception as e:
# Catch other formatting errors
frappe.log_error(f"Error formatting amount: {e}")
formatted_amount = f"{amount} {currency}"
# ---> CHANGE IS HERE <---
try:
# Assuming doc.donation_date exists (Changed from posting_date)
donation_date = doc.get("donation_date") # Changed field name from "posting_date"
formatted_date = frappe.utils.formatdate(donation_date) if donation_date else "N/A" # Use donation_date variable
except AttributeError:
frappe.log_error("frappe.utils.formatdate not accessible in server script")
formatted_date = str(donation_date) if donation_date else "N/A" # Use donation_date variable
except Exception as e:
frappe.log_error(f"Error formatting date: {e}")
formatted_date = str(donation_date) if donation_date else "N/A" # Use donation_date variable
# ---> END OF CHANGE <---
donor_name = doc.get("donor_name") or 'Donor' # Use .get for safety
# Example message body (using fetched/formatted values)
# Ensure fields like 'donor_name', 'amount', 'currency', 'donation_date' exist on your DocType
message = f"""
Dear {donor_name},
Thank you for your generous donation!
Reference ID: {doc.name}
Amount: {formatted_amount}
Donation Date: {formatted_date} # This now uses the value from donation_date field
We truly appreciate your support.
Sincerely,
[Your Organization Name]
(This is an automated message)
“”"
# — End Customize Email Content —
# Send the email using Frappe’s standard mail function
frappe.sendmail(
recipients=[recipient_email],
subject=subject,
message=message,
reference_doctype=doctype,
reference_name=doc_name
# Optional: Specify a sender if needed and configured
# sender="donations@yourorg.com"
)
console.log(recipient_email,subject,message,doctype,doc_name)
# Use Frappe's messaging to give feedback on success
frappe.msgprint(
_("Email successfully sent to {0}").format(recipient_email),
title=_("Success"),
indicator="green"
)
return {"status": "success", "message": f"Email sent to {recipient_email}"}
except Exception as e:
# Log the detailed error on the server for debugging
frappe.log_error(
title=f"Send Donation Receipt Error ({doctype} {doc_name})",
message=frappe.get_traceback()
)
# Throw an error message back to the client script
frappe.throw(f"Failed to send email: {str(e)}")