Help for mail.send

mail ยท send

Sample CLI

gway mail send

References

Full Code

def send(subject, body=None, to=None, threaded=None, **kwargs):
    """
    Send an email with the specified subject and body, using defaults from env if available.

    Parameters:
    - subject: the email subject (string)
    - body:    the plain-text body (string). Must be provided.
    - to:      recipient address (string). Defaults to ADMIN_EMAIL from the environment.
    - threaded:  if True, send the email asynchronously; if False, block and send; if None, auto-detect.
    - **kwargs: reserved for future use.

    Returns:
        str ("Email sent successfully to ...") or error message, unless threaded is True (returns immediately).
    """

    def _send_email():
        _to = to or os.environ.get("ADMIN_EMAIL")
        if not body:
            gw.debug("No email body provided.")
            return "No email body provided."

        gw.debug(f"Preparing to send email to {_to}: {subject}")

        # Load SMTP configuration from environment
        sender_email    = os.environ.get("MAIL_SENDER")
        sender_password = os.environ.get("MAIL_PASSWORD")
        smtp_server     = os.environ.get("SMTP_SERVER")
        smtp_port       = os.environ.get("SMTP_PORT")

        gw.debug(f"MAIL_SENDER: {sender_email}")
        gw.debug(f"SMTP_SERVER: {smtp_server}")
        gw.debug(f"SMTP_PORT: {smtp_port}")
        gw.debug("Environment variables loaded.")

        # If any required piece is missing, bail out
        if not all([sender_email, sender_password, smtp_server, smtp_port]):
            gw.debug("Missing one or more required email configuration details.")
            return "Missing email configuration details."

        # Construct the MIMEText message
        msg = MIMEText(body)
        msg['Subject'] = gw.resolve(subject)
        msg['From']    = sender_email
        msg['To']      = _to

        gw.debug("Email MIME message constructed.")
        gw.debug(f"Email headers: From={msg['From']}, To={msg['To']}, Subject={msg['Subject']}")

        try:
            gw.debug(f"Connecting to SMTP server: {smtp_server}:{smtp_port}")
            server = smtplib.SMTP(smtp_server, int(smtp_port))
            gw.debug("SMTP connection established. Starting TLS...")
            server.starttls()
            gw.debug("TLS started. Logging in...")  
            server.login(sender_email, sender_password)
            gw.debug("Login successful. Sending message...")
            server.send_message(msg)
            server.quit()
            gw.debug("Email sent and SMTP session closed.")
            return "Email sent successfully to " + _to
        except Exception as e:
            gw.debug(f"Exception occurred while sending email: {e}")
            return f"Error sending email: {e}"

    # Auto-detect async mode if not specified
    if threaded is None:
        try:
            asyncio.get_running_loop()
            threaded = True
        except RuntimeError:
            threaded = False

    if threaded:
        try:
            loop = asyncio.get_running_loop()
            async def async_task():
                result = await asyncio.to_thread(_send_email)
                if result and "Error" in result:
                    gw.error(result)
            asyncio.create_task(async_task())
        except RuntimeError:
            def thread_task():
                result = _send_email()
                if result and "Error" in result:
                    gw.error(result)
            threading.Thread(target=thread_task, daemon=True).start()
        return "Email send scheduled (async mode)"
    else:
        return _send_email()