はじめに
添付ファイルが1つであればSDKを使用して比較的簡単に送信することができますが、複数の場合はMIME形式で記載する必要があります。
※この記事は基本的にJavaScriptでサンプルコードを記載するため、PHPやPythonなどの別言語の場合は考え方だけ参考にしていただき、それぞれのプログラミング言語ごとの記載方法に置き換えてください。
実装前の確認事項について
AWS SESで添付ファイルを扱う上で、いくつか注意点があります。
最低限の内容は下記に記載していますが、AWS側で仕様が変更される可能性もあるため、必要な場合は公式ドキュメントなどを確認してください。
https://docs.aws.amazon.com/ja_jp/ses/latest/dg/quotas.html
メールサイズの制限
添付ファイル自体にサイズの制限はありませんが、メール全体(本文 + 添付ファイル + その他設定値) で下記の制限を超えるとエラーが発生するため、添付ファイルについてはv1で1~5MB、v2で20~30MBくらいに抑えておくと良いでしょう。
- SES v1 APIの場合
- 送信の場合:10MBまで
- 受信の場合:30MBまで
- SES v2 API、または SMTPの場合
- 送信の場合:40MBまで
- 受信の場合:40MBまで
添付ファイル個数の制限
公式ドキュメント上では明示な添付ファイル数の制限はありませんが、上記のメールサイズ制限により実質的なファイル数は制限されます。
Base64エンコードの影響
添付ファイルを送信する際、base64形式でエンコードされるため、元々のファイルサイズより大きくなる恐れがあります。
複数の添付ファイルを送信する方法について
AWS SDKを使用してSESでメールを送る場合、「Simple方式」「Raw形式」「Template形式」の3種類の記載方法がありますが、3種類の中で複数の添付ファイルの送信に対応しているのは 「Raw形式」のみ になります。
- Simple方式
- Raw方式
- v1:SendRawEmail
- v2:SendEmail
- Template方式
また、SESのSDKに関しては、「v1」と「v2」という2種類のバージョンがあり、それぞれで使用する関数が異なるため注意してください。
※特に事情がなければ「v2」の方を使用しましょう。
サンプルコード
v1とv2の場合のサンプルコードをそれぞれ下記に記載します。
MIME形式でメールデータを生成する際、送信情報やメール本文、添付ファイルなどを1つにまとめ、「boundary」によってそれぞれのデータ領域を識別しています。
SES v1の場合
const {SESClient, SendRawEmailCommand} = require("@aws-sdk/client-ses");
async function sendSesV1Mail(toAddress, subject, body, attachmentFiles = null) {
// boundaryによって添付ファイルや設定情報などが区分けされている
const boundary = "NextPart"; // メールの境界を定義
// SES インスタンスを作成
const ses = new SESClient({region: "ap-northeast-1"});
// 添付ファイルが存在する場合のMINEの記載
// ファイルの情報はbase64形式で挿入
let attachmentParams = '';
if (attachmentFiles !== null) {
for(const value of attachmentFiles) {
attachmentParams += [
`--${boundary}\r\n`,
`Content-Type: ${value.fileType}; name="${value.fileName}"\r\n`,
`Content-Disposition: attachment; filename="${value.fileName}"\r\n`,
`Content-Transfer-Encoding: base64\r\n\r\n`,
`"${value.fileBase64Data}"\r\n\r\n`,
].join('');
}
attachmentParams += `--${boundary}--`;
}
// メール送信関数
const fromMailAddress = 'info@hogehoge.com';
const params = {
Source: fromMailAddress, // 送信元のメールアドレス
Destinations: [toAddress], // 送信先のメールアドレス
RawMessage: {
Data: [
`From: ${fromMailAddress}\r\n`,
`To: ${toAddress}\r\n`,
`Subject: ${subject}\r\n`,
`MIME-Version: 1.0\r\n`,
`Content-Type: multipart/mixed; boundary="${boundary}"\r\n\r\n`,
`--${boundary}\r\n`,
`Content-Type: text/plain; charset="UTF-8"\r\n`,
`Content-Transfer-Encoding: 7bit\r\n\r\n`,
`${body}\r\n\r\n`,
`${attachmentParams}`
].join('')
}
};
const command = new SendRawEmailCommand(params);
// メール送信ログ
try {
const result = await ses.send(command);
} catch (error) {
console.error("Email送信エラー:", error);
}
}
let targetMailAddress = '送信先のメールアドレス';
let subject = `メールの件名`;
let mailBody = `メールの本文内容`;
// 添付ファイル情報のサンプル
let attachmentFiles = [
{
fileName: '添付ファイル1', // ファイル名
fileType: 'application/pdf', // ファイルのタイプ
fileBase64Data: 'koepdoewkweopjfiwepjfpiw~~~~', // base64形式に変換した添付ファイルのデータ
},
{
fileName: '添付ファイル2', // ファイル名
fileType: 'application/pdf', // ファイルのタイプ
fileBase64Data: 'koepdoewkweopjfiwepjfpiw~~~~', // base64形式に変換した添付ファイルのデータ
}
];
// メール送信用の関数を実行
await sendSesV1Mail(targetMailAddress, subject, mailBody, attachmentFiles);
SES v2の場合
const {SESv2Client, SendEmailCommand} = require("@aws-sdk/client-sesv2");
async function sendSesV2Mail(toAddress, subject, body, attachmentFiles = null) {
let isSendEmail = true;
// boundaryによって添付ファイルや設定情報などが区分けされている
const boundary = "NextPart"; // メールの境界を定義
// SES インスタンスを作成
const ses = new SESv2Client({region: "ap-northeast-1"});
// 添付ファイルが存在する場合のMINEの記載
// ファイルの情報はbase64形式で挿入
let attachmentParams = '';
if (attachmentFiles !== null) {
for(const value of attachmentFiles) {
attachmentParams += [
`--${boundary}\r\n`,
`Content-Type: ${value.fileType}; name="${value.fileName}"\r\n`,
`Content-Disposition: attachment; filename="${value.fileName}"\r\n`,
`Content-Transfer-Encoding: base64\r\n\r\n`,
`"${value.fileBase64Data}"\r\n\r\n`,
].join('');
}
attachmentParams += `--${boundary}--`;
}
// メール送信関数
const fromMailAddress = 'info@hogehoge.com';
const params = {
FromEmailAddress: fromMailAddress, // 送信元のメールアドレス
Destination: {
ToAddresses: [toAddress],
},
Content: {
Raw: {
Data: [
`From: ${fromMailAddress}\r\n`,
`To: ${toAddress}\r\n`,
`Subject: ${subject}\r\n`,
`MIME-Version: 1.0\r\n`,
`Content-Type: multipart/mixed; boundary="${boundary}"\r\n\r\n`,
`--${boundary}\r\n`,
`Content-Type: text/plain; charset="UTF-8"\r\n`,
`Content-Transfer-Encoding: 7bit\r\n\r\n`,
`${body}\r\n\r\n`,
`${attachmentParams}`
].join('');
},
},
};
const command = new SendEmailCommand(params);
// メール送信ログ
try {
const result = await ses.send(command);
console.log(result);
if(result.$metadata.httpStatusCode !== 200) isSendEmail = false;
} catch (error) {
console.error("Email送信エラー:", error);
isSendEmail = false;
}
return isSendEmail;
}
let targetMailAddress = '送信先のメールアドレス';
let subject = `メールの件名`;
let mailBody = `メールの本文内容`;
// 添付ファイル情報のサンプル
let attachmentFiles = [
{
fileName: '添付ファイル1', // ファイル名
fileType: 'application/pdf', // ファイルのタイプ
fileBase64Data: 'koepdoewkweopjfiwepjfpiw~~~~', // base64形式に変換した添付ファイルのデータ
},
{
fileName: '添付ファイル2', // ファイル名
fileType: 'application/pdf', // ファイルのタイプ
fileBase64Data: 'koepdoewkweopjfiwepjfpiw~~~~', // base64形式に変換した添付ファイルのデータ
}
];
// メール送信用の関数を実行
const isSendEmail = await sendSesV2Mail(targetMailAddress, subject, mailBody, attachmentFiles);
if (isSendEmail) {
console.log('メールが正常に送信されました。');
} else {
console.log('メール送信に失敗しました。');
}