Send Email - Your SMTP, Resend or SendGrid, With Attachments avatar

Send Email - Your SMTP, Resend or SendGrid, With Attachments

Pricing

from $2.00 / 1,000 email sents

Go to Apify Store
Send Email - Your SMTP, Resend or SendGrid, With Attachments

Send Email - Your SMTP, Resend or SendGrid, With Attachments

Send transactional notifications and reports through your own SMTP, Resend or SendGrid account - your From address, your deliverability, your provider logs. Attach the run's dataset as CSV/JSON.

Pricing

from $2.00 / 1,000 email sents

Rating

0.0

(0)

Developer

TRUONG VAN HOA

TRUONG VAN HOA

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

Send Email — your own SMTP, Resend or SendGrid, with attachments

Send transactional notifications and reports through your own email account — SMTP (Gmail, Outlook, Zoho, Brevo, Mailgun, Amazon SES...), Resend or SendGrid. Because it's your account, the From name and address, your domain's deliverability (SPF/DKIM) and every provider-side delivery log are yours, not a shared sender's. Attach a run's dataset as a CSV or JSON file, or show a quick HTML preview table of the first rows, right in the email.

This actor is built for notifications and reports - "email me when my scraper finishes", a daily digest, an alert - not for bulk or marketing mail. See Acceptable use below.

Setup recipes

1. Gmail (or any SMTP account) with an App Password

  1. Turn on 2-Step Verification on your Google Account, if it isn't already.
  2. Go to myaccount.google.com/apppasswords, create an app password (any name), and copy the 16-character password shown.
  3. In the input: provider: "smtp", smtpHost: "smtp.gmail.com", smtpPort: 587, smtpSecurity: "starttls", smtpUser = your Gmail address, smtpPassword = the app password (not your normal Google password - Gmail rejects that over SMTP).

Other SMTP providers, same idea (host/port only, your address + a normal or app password):

ProviderHostPort
Outlook / Office 365smtp.office365.com587
Zoho Mailsmtp.zoho.com587
Brevo (Sendinblue)smtp-relay.brevo.com587
Mailgunsmtp.mailgun.org587
Amazon SESemail-smtp.<region>.amazonaws.com587

2. Resend

  1. Sign up at resend.com, verify a sending domain under Domains (or use onboarding@resend.dev as fromEmail for a quick test, no domain needed).
  2. Create an API key under API Keys with send permission.
  3. In the input: provider: "resend", apiKey = the key, fromEmail = an address on your verified domain (or onboarding@resend.dev for testing).

3. SendGrid

  1. Sign up at sendgrid.com, verify a sender identity or domain under Settings > Sender Authentication.
  2. Create an API key under Settings > API Keys with Mail Send permission.
  3. In the input: provider: "sendgrid", apiKey = the key, fromEmail = the verified sender/domain address.

"Email me when my scraper finishes" (Integrations)

Chain this actor after any other Actor via Integrations, triggered on that Actor's run succeeding, and pass its dataset straight through:

{
"provider": "resend",
"apiKey": "{{secrets.RESEND_API_KEY}}",
"fromEmail": "alerts@yourdomain.com",
"to": "you@yourdomain.com",
"subject": "{{resource.actorName}} finished - {{itemCount}} items",
"text": "Your run is done. {{itemCount}} items were scraped on {{date}}.",
"datasetId": "{{resource.defaultDatasetId}}",
"attachmentFormat": "csv",
"includeTablePreview": true
}

{{resource.defaultDatasetId}} and {{resource.actorName}} are filled in by Integrations; {{date}} and {{itemCount}} are filled in by this actor from the dataset it just read.

Example: from the API

curl "https://api.apify.com/v2/acts/YOUR_USERNAME~send-email/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "smtp",
"smtpHost": "smtp.gmail.com",
"smtpUser": "you@gmail.com",
"smtpPassword": "your-app-password",
"fromEmail": "you@gmail.com",
"to": "customer@example.com",
"subject": "Your order shipped",
"text": "Order #1042 is on its way."
}'

Example: from an AI agent (Apify MCP)

An agent that already has a result to report can send it directly, with no dataset involved:

{
"provider": "sendgrid",
"apiKey": "...",
"fromEmail": "bot@yourdomain.com",
"to": "you@yourdomain.com",
"subject": "Task complete",
"text": "The agent finished the requested task successfully."
}

Input reference

FieldNotes
providersmtp | resend | sendgrid
smtpHost, smtpPort, smtpSecurity, smtpUser, smtpPasswordSMTP only
apiKeyResend/SendGrid only, secret input
fromEmail, fromName, replyToSender identity
to, cc, bccComma, semicolon or newline-separated string. Max 20 unique recipients combined - see Acceptable use
subject, text, htmlAt least one of text/html is required. Support {{runId}}, {{datasetId}}, {{itemCount}}, {{date}}
datasetIdAttach and/or preview a dataset, e.g. {{resource.defaultDatasetId}}
attachmentFormatcsv | json | none
attachmentFileName, maxAttachmentRowsAttachment naming/size controls
includeTablePreview, previewRowsAppend an HTML table of the first rows to the body
extraAttachments[{fileName, url}] (https only) or [{fileName, contentBase64, contentType}]
dryRunValidate and build the message without sending, not charged

Attachments (dataset + extraAttachments combined) are capped at 10 MB after encoding - a run over that fails before sending, with a message telling you which input to lower.

Output

OUTPUT (key-value store record), also pushed as one dataset item:

{
"status": "sent",
"provider": "resend",
"messageId": "4ef9...",
"from": "Acme Alerts <alerts@yourdomain.com>",
"recipientsCount": 2,
"subject": "Weekly report - 128 items",
"attachment": { "fileName": "dataset-abc123-2026-09-27.csv", "rows": 128, "bytes": 9421 },
"previewRows": 10,
"sentAt": "2026-09-27T08:00:00.000Z",
"warnings": []
}

status is "sent", "dry-run", or "setup-required". A run started with no login details at all (no SMTP host/username/password and no API key - e.g. the untouched prefilled form) does not fail: it finishes with status: "setup-required", sends nothing, pushes no dataset item and is not charged. The status message and OUTPUT.message say what to fill in. Partial or wrong details (host but no password, a rejected API key, ...) still fail the run with an actionable message.

Acceptable use

This actor is for transactional notifications and reports to recipients who expect them - run alerts, digests, order/status updates. It is not a bulk or marketing mailer:

  • Recipients come only from to/cc/bcc — never from a dataset. There is no mail-merge mode.
  • A hard cap of 20 unique recipients per run (to+cc+bcc combined) - a run over the cap fails before sending.
  • One message per run to every recipient on it (bcc hides the extra recipients from each other) - no per-recipient loops.

Cold outreach, purchased lists, or scraped contact data are forbidden by every provider this actor can use — quoting Resend's Acceptable Use Policy: "You are prohibited from sending unsolicited messages of any kind, including cold outreach, purchased lists, or scraped contact data." The same applies here. Runs that look like bulk/marketing sending may be blocked by your own SMTP/Resend/ SendGrid account regardless of what this actor allows.

Pricing

Pay per event, charged only once the provider actually accepts the message — a failed run or a validation error (bad address, over a cap) costs nothing:

EventPriceWhen
email-sent$0.002Once per message the provider accepted
attachment-rows-1000$0.001Per started block of 1,000 dataset rows attached or previewed

A single notification with no attachment costs $0.002. A report with a 2,000-row CSV attached costs $0.002 + $0.002 = $0.004. If Max total charge can't cover even one email-sent event, the run fails before attempting to send.

FAQ

Why does this land in the inbox instead of spam? Because it's sent through your SMTP account or your verified Resend/SendGrid domain, it inherits your domain's own SPF/DKIM/reputation - the same signals mailbox providers use to trust any other mail from you. A shared sender used by many unrelated actors can't offer that.

Is my password/API key safe? smtpPassword and apiKey are Apify secret inputs: encrypted at rest, never shown in logs, used only in memory for the run's duration. This actor never logs a password, API key, or full message body, and redacts anything that looks like a secret from error messages before they're shown. Nothing is stored beyond the run itself.

Can I send to more than 20 people? Split into multiple runs, or use your provider's own mailing-list/broadcast feature - this actor is deliberately capped for notifications/reports (see Acceptable use).

What happens if my dataset is huge? maxAttachmentRows (default 50,000) caps how many rows are attached; the combined attachment size (dataset + extraAttachments) is capped at 10 MB after encoding. Over either limit, the run fails before sending with the exact input to lower.

Gmail says "Invalid login" / "Application-specific password required". Use an App Password (Google Account > Security > App passwords), not your normal Gmail password - Gmail rejects normal passwords over SMTP for accounts with 2-Step Verification on.

Is this affiliated with Google, Resend or Twilio SendGrid? No. This is an independent tool that uses each provider's official public API/SMTP interface with your own credentials in your own account.

Something wrong or missing? Open an issue on the Actor's Issues tab.