Custom Email Sending

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)}")