mirror of
https://github.com/dawidd6/action-send-mail.git
synced 2026-03-14 13:23:13 +07:00
Fix 234 (#271)
* Fix envelope handling * Updated documentation * Update main.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Implemented review suggestions * Implemented review suggestions * Implemented review suggestions * Use nodemailer's addressparser instead of regular expressions * Updated README regarding address formats * Updated README regarding address formats * Update README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Use addressparser regardless of envelopeX ist set or not. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
56
README.md
56
README.md
@@ -27,54 +27,86 @@ Some features:
|
|||||||
# * smtp://user:password@server:port
|
# * smtp://user:password@server:port
|
||||||
# * smtp+starttls://user:password@server:port
|
# * smtp+starttls://user:password@server:port
|
||||||
connection_url: ${{secrets.MAIL_CONNECTION}}
|
connection_url: ${{secrets.MAIL_CONNECTION}}
|
||||||
|
|
||||||
# Required mail server address if not connection_url:
|
# Required mail server address if not connection_url:
|
||||||
server_address: smtp.gmail.com
|
server_address: smtp.gmail.com
|
||||||
|
|
||||||
# Server port, default 25:
|
# Server port, default 25:
|
||||||
server_port: 465
|
server_port: 465
|
||||||
|
|
||||||
# Optional whether this connection use TLS (default is true if server_port is 465)
|
# Optional whether this connection use TLS (default is true if server_port is 465)
|
||||||
secure: true
|
secure: true
|
||||||
|
|
||||||
# Optional (recommended) mail server username:
|
# Optional (recommended) mail server username:
|
||||||
username: ${{secrets.MAIL_USERNAME}}
|
username: ${{secrets.MAIL_USERNAME}}
|
||||||
|
|
||||||
# Optional (recommended) mail server password:
|
# Optional (recommended) mail server password:
|
||||||
password: ${{secrets.MAIL_PASSWORD}}
|
password: ${{secrets.MAIL_PASSWORD}}
|
||||||
|
|
||||||
# Required mail subject:
|
# Required mail subject:
|
||||||
subject: Github Actions job result
|
subject: Github Actions job result
|
||||||
# Optional recipients' addresses:
|
|
||||||
to: obiwan@example.com,yoda@example.com
|
# Optional recipients. Separate multiple addresses by a comma (possibly surrounded by whitespace):
|
||||||
# Required sender (Either: "Plain Simple Name <user@doma.in>" or just "user@doma.in" (without the <>))
|
to: obiwan@example.com, yoda@example.com
|
||||||
# Important: '<' and '>' are special chars in yaml. Therefore this string should be quoted
|
|
||||||
|
# Required sender (supported formats: see "Supported address formats" below)
|
||||||
from: 'Luke Skywalker <user@example.com>'
|
from: 'Luke Skywalker <user@example.com>'
|
||||||
|
|
||||||
# Optional plain body:
|
# Optional plain body:
|
||||||
body: Build job of ${{github.repository}} completed successfully!
|
body: Build job of ${{github.repository}} completed successfully!
|
||||||
|
|
||||||
# Optional HTML body read from file:
|
# Optional HTML body read from file:
|
||||||
html_body: file://README.html
|
html_body: file://README.html
|
||||||
# Optional carbon copy recipients:
|
|
||||||
cc: kyloren@example.com,leia@example.com
|
# Optional carbon copy recipients. Separate multiple addresses by a comma (possibly surrounded by whitespace):
|
||||||
# Optional blind carbon copy recipients:
|
cc: 'kyloren@example.com, "Her Majesty, Princess Leia" <leia@example.com>'
|
||||||
bcc: r2d2@example.com,hansolo@example.com
|
|
||||||
|
# Optional blind carbon copy recipients. Separate multiple addresses by a comma (possibly surrounded by whitespace):
|
||||||
|
bcc: r2d2@example.com, hansolo@example.com
|
||||||
|
|
||||||
# Optional recipient of the email response:
|
# Optional recipient of the email response:
|
||||||
reply_to: luke@example.com
|
reply_to: luke@example.com
|
||||||
|
|
||||||
# Optional Message ID this message is replying to:
|
# Optional Message ID this message is replying to:
|
||||||
in_reply_to: <random-luke@example.com>
|
in_reply_to: '<3cc627c8-6181-453b-d90b-04aae9e23b21@github.com>'
|
||||||
|
|
||||||
# Optional unsigned/invalid certificates allowance:
|
# Optional unsigned/invalid certificates allowance:
|
||||||
ignore_cert: true
|
ignore_cert: true
|
||||||
|
|
||||||
# Optional converting Markdown to HTML (set content_type to text/html too):
|
# Optional converting Markdown to HTML (set content_type to text/html too):
|
||||||
convert_markdown: true
|
convert_markdown: true
|
||||||
|
|
||||||
# Optional attachments:
|
# Optional attachments:
|
||||||
attachments: attachments.zip,git.diff,./dist/static/*.js
|
attachments: attachments.zip,git.diff,./dist/static/*.js
|
||||||
|
|
||||||
# Optional priority: 'high', 'normal' (default) or 'low'
|
# Optional priority: 'high', 'normal' (default) or 'low'
|
||||||
priority: low
|
priority: low
|
||||||
|
|
||||||
# Optional custom headers:
|
# Optional custom headers:
|
||||||
headers: '{"X-Priority": "3 (Normal)", "X-My-Header": "MyValue"}'
|
headers: '{"X-Priority": "3 (Normal)", "X-My-Header": "MyValue"}'
|
||||||
|
|
||||||
# Optional nodemailerlog: true/false
|
# Optional nodemailerlog: true/false
|
||||||
nodemailerlog: false
|
nodemailerlog: false
|
||||||
# Optional nodemailerdebug: true/false if true lognodem will also be set true
|
|
||||||
|
# Optional nodemailerdebug: true/false if true nodemailerlog will also be set true
|
||||||
nodemailerdebug: false
|
nodemailerdebug: false
|
||||||
|
|
||||||
# Optional custom SMTP MAIL FROM address (overrides username):
|
# Optional custom SMTP MAIL FROM address (overrides username):
|
||||||
envelope_from: mailer@example.com
|
envelope_from: mailer@example.com
|
||||||
# Optional custom SMTP RCPT TO addresses (overrides to, cc, bcc):
|
|
||||||
envelope_to: mailer@example.com,admin@example.com
|
# Optional custom SMTP RCPT TO addresses (overrides to, cc, bcc). Separate multiple addresses by a comma (possibly surrounded by whitespace):
|
||||||
|
envelope_to: mailer@example.com, admin@example.com
|
||||||
```
|
```
|
||||||
|
### Remark for `envelope_from` and `envelope_to`
|
||||||
|
|
||||||
|
[nodemailer](https://nodemailer.com/) (the node module that does the actual sending) requires that if the optional custom envelope is used, **both** its attributes `from` and `to` must be set. To facilitate setting only one of `envelope_from` or `envelope_to`, this action sets the other one from the regular message fields in the following way:
|
||||||
|
|
||||||
|
* If only `envelope_from` is set, `envelope_to` will be set to the concatenation of `to`, `cc` and `bcc` (with duplicates removed).
|
||||||
|
* If only `envelope_to` is set, `envelope_from` will be set to the address specified in `from`.
|
||||||
|
|
||||||
|
### Supported address formats
|
||||||
|
This action now uses nodemailer's addressparser. The supported address formats are described [here](https://nodemailer.com/message/addresses).
|
||||||
|
Mail addresses can contain YAML special characters like '<' and '>'. To avoid YAML parsing issues, addresses that contain such characters should be enclosed in single quotes.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
|
|||||||
57
main.js
57
main.js
@@ -1,4 +1,5 @@
|
|||||||
import nodemailer from "nodemailer";
|
import nodemailer from "nodemailer";
|
||||||
|
import addressparser from "nodemailer/lib/addressparser/index.js";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import * as glob from "@actions/glob";
|
import * as glob from "@actions/glob";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
@@ -39,6 +40,39 @@ function sleep(ms) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare an envelope object for nodemailer.
|
||||||
|
*
|
||||||
|
* If only one of envelopeFrom or envelopeTo is set, make sure that both
|
||||||
|
* are set in the returned object. Furthermore, make sure that the attribute 'to'
|
||||||
|
* is an array of email addresses, not a comma-separated string.
|
||||||
|
*/
|
||||||
|
function setupEnvelope(envelopeFrom, envelopeTo, from, to, cc, bcc) {
|
||||||
|
if (envelopeFrom || envelopeTo) {
|
||||||
|
// Take address in from, if envelopeFrom is not set.
|
||||||
|
envelopeFrom = envelopeFrom ? addressparser(envelopeFrom) : addressparser(from);
|
||||||
|
if (envelopeFrom.length != 1 || envelopeFrom[0].address == '') {
|
||||||
|
throw new Error("'envelopeFrom' address is invalid");
|
||||||
|
}
|
||||||
|
if (envelopeTo) {
|
||||||
|
envelopeTo = addressparser(envelopeTo);
|
||||||
|
} else {
|
||||||
|
// Take addresses in to, cc and bcc. Deduplication is handled by nodemailer.
|
||||||
|
for (const src of [to, cc, bcc]) {
|
||||||
|
if (src) {
|
||||||
|
let parsed = addressparser(src);
|
||||||
|
envelopeTo = envelopeTo ? envelopeTo.concat(parsed) : parsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
from: envelopeFrom,
|
||||||
|
to: envelopeTo,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
try {
|
try {
|
||||||
let serverAddress = core.getInput("server_address");
|
let serverAddress = core.getInput("server_address");
|
||||||
@@ -111,7 +145,8 @@ async function main() {
|
|||||||
|
|
||||||
// Basic check for an email sender address
|
// Basic check for an email sender address
|
||||||
// Either: "Plain Simple Name <user@doma.in>" or just "user@doma.in" (without the <>)
|
// Either: "Plain Simple Name <user@doma.in>" or just "user@doma.in" (without the <>)
|
||||||
if (!(/^([^<>@\s]+\s+)+<[^@\s>]+@[^@\s>]+>$/.test(from) || /^[^<>@\s]+@[^@\s<>]+$/.test(from))) {
|
let parsed = addressparser(from);
|
||||||
|
if (parsed.length != 1 || parsed[0].address == '') {
|
||||||
throw new Error("'from' address is invalid");
|
throw new Error("'from' address is invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,10 +183,7 @@ async function main() {
|
|||||||
proxy: process.env.HTTP_PROXY,
|
proxy: process.env.HTTP_PROXY,
|
||||||
});
|
});
|
||||||
|
|
||||||
let i = 1;
|
const messageOptions = {
|
||||||
while (true) {
|
|
||||||
try {
|
|
||||||
const info = await transport.sendMail({
|
|
||||||
from: from,
|
from: from,
|
||||||
to: to,
|
to: to,
|
||||||
subject: getText(subject, false),
|
subject: getText(subject, false),
|
||||||
@@ -169,14 +201,13 @@ async function main() {
|
|||||||
attachments: attachments
|
attachments: attachments
|
||||||
? await getAttachments(attachments)
|
? await getAttachments(attachments)
|
||||||
: undefined,
|
: undefined,
|
||||||
envelope:
|
envelope: setupEnvelope(envelopeFrom, envelopeTo, from, to, cc, bcc),
|
||||||
envelopeFrom || envelopeTo
|
};
|
||||||
? {
|
|
||||||
from: envelopeFrom ? envelopeFrom : undefined,
|
let i = 1;
|
||||||
to: envelopeTo ? envelopeTo : undefined,
|
while (true) {
|
||||||
}
|
try {
|
||||||
: undefined,
|
const info = await transport.sendMail(messageOptions);
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!error.message.includes("Try again later,")) {
|
if (!error.message.includes("Try again later,")) {
|
||||||
|
|||||||
Reference in New Issue
Block a user