← All ivy-nodes
IVYXSTUDIO · IVY NODE
E

Email Send

ivy.node.email-send · v0.1.0

ivyx✓

Sends a plain-text or HTML email through an SMTP server in one step and returns the recipients it went to. TLS and login are optional, so a local relay works as well as a mail provider; reference the password as a stored secret.

#email#smtp#send#notify#mail

Inputs

FieldTypeDescription
smtp_hostrequiredstringThe SMTP server, such as smtp.example.com or localhost for a local relay.
smtp_portintegerThe port: 587 for STARTTLS, 1025 for mailpit.
from_addrrequiredstringThe sender address.
torequiredNot declaredOne address, several separated by commas, or a list.
subjectrequiredstringThe subject line.
bodyrequiredstringThe plain-text body.
htmlstringAn HTML version of the body, sent alongside it.
use_tlsbooleanUpgrade with STARTTLS. On by default on port 587; port 465 is always TLS.
usernamestringLogin name, when the server needs one.
passwordstringLogin password; reference a stored secret instead of writing it.

Outputs

FieldTypeDescription
sentrequiredbooleanTrue once the server accepted the message.
recipientsrequiredarrayThe addresses it was accepted for.
subjectrequiredstringThe subject sent.

Source

python

inp = __ivy_ctx__["nodes"][__ivy_node_id__]["input"]

import smtplib
from email.message import EmailMessage

host = inp["smtp_host"]
port = int(inp.get("smtp_port", 587))
sender = inp["from_addr"]
to = inp["to"]
recipients = [a.strip() for a in (to if isinstance(to, list) else str(to).split(",")) if a and a.strip()]
if not recipients:
    raise ValueError("There is no recipient.")
message = EmailMessage()
message["From"] = sender
message["To"] = ", ".join(recipients)
message["Subject"] = inp["subject"]
message.set_content(inp["body"])
if inp.get("html"):
    message.add_alternative(inp["html"], subtype="html")
# 465 is TLS from the first byte; 587 upgrades with STARTTLS; anything else
# (25, a local relay on 1025) is plain unless use_tls says otherwise.
connect = smtplib.SMTP_SSL if port == 465 else smtplib.SMTP
with connect(host, port, timeout=30) as server:
    if port != 465 and inp.get("use_tls", port == 587):
        server.starttls()
    if inp.get("username") and inp.get("password"):
        server.login(inp["username"], inp["password"])
    refused = server.send_message(message) or {}

out = __ivy_ctx__["nodes"][__ivy_node_id__]["output"]
out["sent"] = True
out["recipients"] = [r for r in recipients if r not in refused]
out["subject"] = inp["subject"]

Tests

Requires: python:3.9

  • relay

    A local relay accepts a message for two recipients.

  • no-recipient

    An empty recipient list is refused before connecting.

  • closed-port

    Nothing listening fails the step.