← All ivy-nodes
IVYXSTUDIO · IVY NODE
E
Email Builder
ivy.node.email-builder · v0.0.0
ivyx✓
Builds email messages with optional attachments using Python's email library. This node creates MIMEMultipart email objects with sender, recipient, subject, body, and optional file attachments. The output email_message is used with email-provider node to send emails via SMTP. Supports attachments from BytesIO buffers (e.g., from csv-from-data-frame or chart generators). Use this node to prepare emails before sending them.
#Email
Inputs
| Field | Type | Description |
|---|---|---|
| from_emailrequired | string | Sender's email address. |
| to_emailrequired | string | Recipient's email address. |
| subjectrequired | string | Subject of the email. |
| bodyrequired | string | Body content of the email. |
| file_buffer | Not declared | Optional buffer containing attachment bytes (e.g. io.BytesIO). (Node reference) |
| file_name | Not declared | Optional attachment file name (required if file_buffer is provided). |
| features | object | Features |
| labels | object | Labels |
Outputs
| Field | Type | Description |
|---|---|---|
| email_messagerequired | object | Custom type: MIMEMultipart |
| features | object | Features |
| labels | object | Labels |
Source
python
# Input preparation
inp = __ivy_ctx__["nodes"][__ivy_node_id__]["input"]
from_email = inp["from_email"]
to_email = inp["to_email"]
subject = inp["subject"]
body = inp["body"]
file_buffer = inp.get("file_buffer")
file_name = inp.get("file_name")
# Compute
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from typing import Optional
import io
class EmailBuilder:
"""A class to build and handle email messages with optional attachments."""
def __init__(
self,
from_email: str,
to_email: str,
subject: str,
body: str,
file_buffer: Optional[io.BytesIO] = None,
file_name: Optional[str] = None,
):
self.from_email = from_email
self.to_email = to_email
self.subject = subject
self.body = body
self.file_buffer = file_buffer
self.file_name = file_name
self.email_message = MIMEMultipart()
def build_email(self):
self.email_message['From'] = self.from_email
self.email_message['To'] = self.to_email
self.email_message['Subject'] = self.subject
self.email_message.attach(MIMEText(self.body, 'plain'))
if (self.file_buffer is None) != (self.file_name is None):
raise ValueError('file_buffer and file_name must be provided together (or both be None).')
if self.file_buffer and self.file_name:
self.file_buffer.seek(0)
attachment = MIMEBase('application', 'octet-stream')
attachment.set_payload(self.file_buffer.getvalue())
encoders.encode_base64(attachment)
attachment.add_header(
'Content-Disposition',
f'attachment; filename="{self.file_name}"'
)
self.email_message.attach(attachment)
def get_email(self):
return self.email_message
email_builder = EmailBuilder(
from_email=from_email,
to_email=to_email,
subject=subject,
body=body,
file_buffer=file_buffer,
file_name=file_name
)
email_builder.build_email()
email_message = email_builder.get_email()
# Output collection (runner reads __ivy_ctx__)
out = __ivy_ctx__["nodes"][__ivy_node_id__]["output"]
out["email_message"] = email_messageTests
Requires: python:3.11
- basic-no-attachment
Build email without attachment (should succeed).
emailbasic - error-mismatched-attachment-pair
file_buffer without file_name should raise an error.
error-handlingvalidation