S3にファイルアップロードしたタイミングでLambdaを実行してSESで添付メール送信する方法

S3にファイルアップロードしたタイミングでLambdaを実行してSESで添付メール送信する方法

S3のPUTイベントでEメールを送信する方法は「JavaからS3にアップロードしてSNSを使ってメールを送信する方法」で紹介しました。

今回はS3にアップロードされたタイミングでLambdaを実行してSESでEメール送信してみます。その際にS3にアップロードされたファイルを添付してEメール送信します。

S3にファイルアップロードしたタイミングでLambdaを実行してSESでメール送信する方法

トリガーをS3にして、Lambdaにはこんな権限上げたらとりあえず良いと思われます。

Lambdaはnode.js8.10使用しています。

const AWS = require('aws-sdk');
AWS.config = new AWS.Config();
AWS.config.region = "us-east-1";

exports.handler = async (event) => {
  const ses = new AWS.SES();

  const param = {
    Source: 'takakashi@confrage.com',
    Destination: {
      ToAddresses: ['takahashi@example.com']
    },
    Message: {
      Subject: {
        Data: 'タイトル'
      },
      Body: {
        Text: {
          Data: '本文です',
        }
      }
    }
  };

  await ses.sendEmail(param, function(err, data) {
    if (err) console.log(err, err.stack);
    else console.log('successful');
  }).promise();
};

特に気をつけるところはありませんが、リージョンはSESのリージョンにして下さい。私はバージニア北部なのでus-east-1です。

とりあえずJavaのプログラムからS3にファイルをアップロードしてみます。

すると、Lambdaが実行されて、SESサービスによってメールが送信されることが確認できます。

SESではファイルを添付することが出来ますので、ちょっと修正してファイル添付したメールを送信するようにしてみます。

SESでファイル添付してメール送信する

添付してメール送信したい場合はsendRawEmailを使用しますが、ちょっと便利なモジュールを発見したのでnodemailerを使ってみます。

npm install nodemailer --save

7zipなどで固めて一旦Lambdaにアップロードしてください。

アップロードしたらインラインで以下をコーディングすればよいです。

const AWS = require('aws-sdk');
AWS.config = new AWS.Config();
AWS.config.region = "us-east-1";
const nodemailer = require('nodemailer');

function send() {
  const transporter = nodemailer.createTransport({
    SES: new AWS.SES({
      apiVersion: '2010-12-01'
    })
  });
  return new Promise(resolve => {
    transporter.sendMail({
      from: 'takahashi@confrage.com',
      to: 'takahashi@example.com',
      subject: 'タイトルです',
      text: '本文です',
      attachments: [
        {
          filename: 'text1.txt',
          content: 'hello world!'
        }
      ]
    },
    (err) => {
      if (err) console.log(err, err.stack);
      else console.log('successful');
    });
  });
}

exports.handler = async (event) => {
  await send();
};

node.js8.10ではasyncファンクションになっているので、sendメソッドをasyncファンクションにしてawaitさせる必要があります。

参考サイト

公式サイト

JavaでアップロードしたファイルをS3から取得してメールに添付する

Lambdaでは/tmpディレクトリが一時的に使用できるのでバケットから取得したファイルを一旦/tmp配下に同じ名前のファイルを置いて、その中身を書いたファイルをメールに添付して送信してみます。

もっと簡単に実装する方法はあるかもしれません。

const AWS = require('aws-sdk');
AWS.config = new AWS.Config();
AWS.config.region = "us-east-1";
const s3 = new AWS.S3({'region':'ap-northeast-1'});
const fs = require('fs');
const nodemailer = require('nodemailer');

function send(fullPath) {
  const transporter = nodemailer.createTransport({
    SES: new AWS.SES({
      apiVersion: '2010-12-01'
    })
  });
  return new Promise(resolve => {
    transporter.sendMail({
      from: 'takakashi@confrage.com',
      to: 'takakashi@example.com',
      subject: '本文です',
      text: 'タイトルです',
      attachments: [
        {
          path: fullPath
        }
      ]
    },
    (err) => {
      if (err) console.log(err, err.stack);
      else console.log('successful');
    });
  });
}

exports.handler = async (event) => {
  const bucket = event.Records[0].s3.bucket.name; // バケット名を取得
  const key = event.Records[0].s3.object.key; // キーを取得

  const config = {
    Bucket: bucket,
    Key: key
  };
  const file = await s3.getObject(config, function(err, data) {
    if (err) {
      if (err) console.log(err, err.stack);
      else console.log('successful');
    }
  }).promise();
  const fullPath = '/tmp/' + key;
  await fs.writeFileSync(fullPath, file.Body.toString("utf-8"), 'utf-8'); // ファイル内容を書き込む

  await send(fullPath);
};

これでJavaからS3へsample.txtというファイルをsaba6seimenjoというバケットにアップロードして、そのタイミングでLambdaが実行されてSESを利用してsample.txtを添付したメールを指定したアドレスに送信することができます。

コメント

タイトルとURLをコピーしました