Как отправить электронное письмо с HTML-контентом из функций Firebase Cloud
Как вы, наверное, догадались, у нас в DeckDeckGo нет сотрудников, которые проверяют, имеют ли публично опубликованные слайды контент по убыванию. Мы также еще не реализовали робота с машинным обучением, который бы это делал.
Я беру на себя такую задачу вручную. Я должен добавить, что это делает меня счастливым. Все опубликованные презентации всегда интересны.
Тем не менее, я должен быть проинформирован, когда колоды будут опубликованы. Вот почему я реализовал Облачную функцию Firebase, чтобы отправлять себе электронное письмо со всей информацией, необходимой мне для быстрого просмотра нового контента.
Настроить новую облачную функцию
Я предполагаю, что у вас уже есть проект Firebase, а также уже созданы некоторые функции. В противном случае вы можете следовать следующему руководству, чтобы начать работу.
Кроме того, обратите внимание, что я использую TypeScript.
Давайте начнем
Для функции нужен триггер, поэтому мы регистрируем функцию в index.ts
в коллекции, называемой, например, demo
(конечно, ваша коллекция может иметь другое имя).
import * as functions from 'firebase-functions'; export const watchCreate = functions. firestore. document('demo/{demoId}').onCreate(onCreateSendEmail);
Мы можем использовать любые другие триггеры или жизненный цикл, не обязательно create
.
Чтобы реагировать на выполнение триггера, мы объявляем новую функцию, которая извлекает вновь созданное значение (const demo = snap.data()
), и пока добавляем TODO
, который следует заменить эффективным методом отправки электронной почты.
import { EventContext } from "firebase-functions"; import { DocumentSnapshot } from "firebase-functions/lib/providers/firestore"; interface Demo { content: string; } async function onCreateSendEmail( snap: DocumentSnapshot, _context: EventContext) { const demo: Demo = snap.data() as Demo; try { // TODO: send email } catch (err) { console.error(err); } }
Nodemailer
Чтобы эффективно отправлять электронную почту, мы будем использовать Nodemailer.
Nodemailer - это модуль для приложений Node.js, позволяющий легко отправлять электронные письма. Проект стартовал еще в 2010 году, когда не было разумного варианта отправки сообщений электронной почты, сегодня это решение, к которому по умолчанию обращается большинство пользователей Node.js.
Nodemailer находится под лицензией MIT.
Как видите, Nodemailer совместим не только с облачными функциями Firebase, но и с любыми проектами Node.js.
Чтобы установить его в нашем проекте, мы запускаем следующую команду:
npm install nodemailer --save
Кроме того, мы также устанавливаем его определение типизации.
npm install @types/nodemailer --save-dev
SMTP транспорт
Nodemailer использует SMTP в качестве основного транспорта для доставки сообщений. Следовательно, ваш поставщик услуг доставки электронной почты должен поддерживать такой протокол. Он также поддерживает расширение LTS или STARTTLS. В этом посте мы собираемся использовать STARTTLS и поэтому собираемся установить флаг secure
на false
, чтобы активировать этот протокол.
Вы можете найти все варианты в библиотеке Документация.
Конфигурация
Если ваш проект имеет открытый исходный код, возможно, вам будет интересно не указывать жестко ваши логин, пароль и хост SMTP в коде, а лучше скрыть их в конфигурации.
Firebase предлагает такую возможность. Мы можем создать сценарий set
для этого.
#!/bin/sh firebase functions:config:set mail.from="[email protected]" mail.pwd="password" mail.to="[email protected]" mail.host="mail.provider.com"
Чтобы получить эту конфигурацию в нашей функции, мы можем получить доступ к конфигурации через functions.config()
, за которым следуют ключи, которые мы только что определили выше.
const mailFrom: string = functions.config().mail.from; const mailPwd: string = functions.config().mail.pwd; const mailTo: string = functions.config().mail.to; const mailHost: string = functions.config().mail.host;
Отправить электронное письмо
У нас есть транспорт, у нас есть конфигурация, нам просто нужна последняя часть: сообщение.
Я предпочитаю отправлять собственное электронное письмо в формате HTML, позволяющее включать ссылки в контент, поэтому и здесь мы используем такой формат.
const mailOptions = { from: mailFrom, to: mailTo, subject: 'Hello World', html: `<p>${demo.content}</p>` };
Наконец, мы можем использовать Nodemailer для создания канала и, в конечном итоге, отправки нашего электронного письма.
const transporter: Mail = nodemailer.createTransport({ host: mailHost, port: 587, secure: false, // STARTTLS auth: { type: 'LOGIN', user: mailFrom, pass: mailPwd } }); await transporter.sendMail(mailOptions);
В целом
В целом наша функция следующая:
import * as functions from 'firebase-functions'; import { EventContext } from "firebase-functions"; import { DocumentSnapshot } from "firebase-functions/lib/providers/firestore"; import * as Mail from "nodemailer/lib/mailer"; import * as nodemailer from "nodemailer"; export const watchCreate = functions. firestore. document('demo/{demoId}').onCreate(onCreateSendEmail); interface Demo { content: string; } async function onCreateSendEmail( snap: DocumentSnapshot, _context: EventContext) { const demo: Demo = snap.data() as Demo; try { const mailFrom: string = functions.config().info.mail.from; const mailPwd: string = functions.config().info.mail.pwd; const mailTo: string = functions.config().info.mail.to; const mailHost: string = functions.config().info.mail.host; const mailOptions = { from: mailFrom, to: mailTo, subject: 'Hello World', html: `<p>${demo.content}</p>` }; const transporter: Mail = nodemailer.createTransport({ host: mailHost, port: 587, secure: false, // STARTTLS auth: { type: 'LOGIN', user: mailFrom, pass: mailPwd } }); await transporter.sendMail(mailOptions); } catch (err) { console.error(err); } }
Резюме
С помощью Firebase и Nodemailer можно относительно быстро настроить функцию, запускающую электронную почту. Я надеюсь, что это введение дало вам несколько подсказок о том, как реализовать такую функцию, и что вы собираетесь попробовать DeckDeckGo в своих следующих презентациях.
Я с нетерпением жду сообщения электронной почты о том, что мне нужно проверить опубликованные вами слайды 😉.
Бесконечность не предел!
Дэйвид