Trong nhiều năm, Quincy Larson đã gửi bản tin email hàng tuần thông qua nền tảng Mail for Good của freeCodeCamp, được cung cấp bởi Amazon SES.
Gần đây anh ấy đã di chuyển quy trình này sang SendGrid. Trong bài viết này, tôi sẽ chỉ cho bạn cách tôi đã xây dựng một công cụ để thực hiện điều này.
Cách thiết lập tài khoản SendGrid
Bước đầu tiên là đăng ký SendGrid và thiết lập tài khoản của bạn. Đối với mục đích của hướng dẫn này, cấp miễn phí phải là đủ.
Khi mở rộng quy mô ứng dụng của mình, bạn có thể cần tăng giới hạn email khả dụng của mình thông qua nền tảng này.
Cách thiết lập địa chỉ IP chuyên dụng trên SendGrid
Theo mặc định, SendGrid sử dụng địa chỉ IP được chia sẻ để gửi email. Điều này có thể được chấp nhận đối với các ứng dụng email quy mô nhỏ hơn, nhưng khi bạn tăng tỷ lệ gửi, bạn sẽ cần thiết lập một địa chỉ IP chuyên dụng.
Đây là một ý tưởng hay vì "danh tiếng người gửi" của bạn (số liệu mà SendGrid sử dụng để đánh giá vị thế của bạn với các nhà cung cấp dịch vụ email) sẽ không bị tác động tiêu cực bởi hành động của những người dùng khác có cùng IP.
Để thiết lập IP chuyên dụng của riêng bạn, hãy chọn tùy chọn "Cài đặt" từ menu điều hướng bên, sau đó chọn "Địa chỉ IP". Tuy nhiên, chỉ cần lưu ý nhanh:tùy chọn này không khả dụng trên cấp miễn phí.
Tùy thuộc vào gói trả phí của bạn, bạn có thể đã thiết lập một địa chỉ IP chuyên dụng. Nếu bạn chưa có hoặc nếu bạn chọn thêm địa chỉ khác, bạn có thể chọn nút "Thêm địa chỉ IP" để định cấu hình một IP mới.
Cách cấp quyền cho người gửi email trong SendGrid
LƯU Ý:bạn có thể bỏ qua phần này nếu bạn đang sử dụng miền tùy chỉnh cho email của mình.
Để gửi email từ địa chỉ email cá nhân của bạn, bạn cần xác minh rằng địa chỉ email đó thuộc về bạn.
Trong menu bên trái, chọn "Cài đặt", sau đó chọn "Xác thực người gửi". Chọn "Xác minh một người gửi" để thực hiện quy trình thêm một địa chỉ email của bạn.
Cách xác thực miền tùy chỉnh của bạn trong SendGrid
LƯU Ý:bạn có thể bỏ qua phần này nếu bạn KHÔNG sử dụng miền tùy chỉnh cho email của mình.
Để gửi email từ miền thư tùy chỉnh của bạn, bạn sẽ cần xác thực miền đó với SendGrid. Để đến màn hình này, hãy chọn lại menu Cài đặt, sau đó chọn "Xác thực người gửi".
Sau đó, bạn sẽ thấy một màn hình có tùy chọn cho "Xác thực miền". Chọn tùy chọn "Xác thực miền của bạn" và SendGrid sẽ hướng dẫn bạn quy trình định cấu hình bản ghi DNS của bạn (với các hướng dẫn cụ thể dựa trên nhà cung cấp DNS của bạn).
Cách thiết lập Reverse DNS trong SendGrid
LƯU Ý:bạn có thể bỏ qua phần này nếu bạn không sử dụng miền tùy chỉnh cho email của mình.
Reverse DNS (Hệ thống tên miền) được các nhà cung cấp dịch vụ email sử dụng để tra cứu chủ sở hữu của một địa chỉ IP nhất định. Việc thiết lập này sẽ cho phép các nhà cung cấp dịch vụ email xác minh rằng địa chỉ IP mà bạn gửi email từ đó được kết nối với miền tùy chỉnh của bạn.
Trong cùng một màn hình Xác thực người gửi như trên, bạn sẽ thấy phần "Reverse DNS". Sẽ có một tùy chọn để định cấu hình DNS ngược cho từng IP chuyên dụng mà bạn có trên tài khoản của mình - như Xác thực miền, nền tảng của SendGrid sẽ hướng dẫn bạn cách thiết lập điều này.
Cách thiết lập xác thực email trong SendGrid
LƯU Ý:bạn có thể bỏ qua phần này nếu bạn không sử dụng miền tùy chỉnh cho email của mình.
Các nhà cung cấp email lớn (chẳng hạn như Gmail, Yahoo và Outlook) sử dụng một số phương pháp để xác thực người gửi email:SPF, DKIM và DMARC.
- SPF (Khung chính sách người gửi) xác thực rằng địa chỉ IP gửi thư từ miền của bạn được phép làm như vậy.
- DKIM (Thư được xác định DomainKeys) sử dụng chuỗi khóa công khai để xác thực rằng một email
from
địa chỉ chính xác và không bị giả mạo / làm sai lệch. - DMARC (Xác thực, báo cáo và tuân thủ tin nhắn dựa trên miền) là một tập hợp các hướng dẫn cho các nhà cung cấp dịch vụ email biết cách phản ứng khi email không xác thực được SPF hoặc DKIM.
Quy trình xác thực của SendGrid sẽ hướng dẫn bạn cách thiết lập SPF và DKIM như một phần của quy trình xác thực miền, nhưng bạn sẽ cần phải định cấu hình DMARC của mình theo cách thủ công.
Truy cập nhà cung cấp dịch vụ lưu trữ DNS của bạn và truy cập cài đặt quản lý DNS. Từ đó, thêm một TXT
mới bản ghi có tên là _dmarc.yourdomain.com
(thay thế yourdomain.com
với miền tùy chỉnh của bạn).
Lưu ý rằng một số nhà cung cấp, chẳng hạn như GoDaddy, sẽ tự động nối miền của bạn vào bản ghi - trong trường hợp này, tên phải là _dmarc
.
Giá trị của bản ghi này phải có cấu trúc tương tự như:
"v=DMARC1; p=none; pct=100; rua=mailto:[email protected]"
-
v=DMARC
cho biết phiên bản của quy tắc DMARC để sử dụng (hiện chỉ có Phiên bản 1). -
p=none
cho biết hành động mà nhà cung cấp email nên thực hiện khi email không DKIM hoặc SPF. Cài đặt này phải bắt đầu lànone
, để tránh ảnh hưởng đến khả năng gửi email của bạn. Khi bạn đã xác nhận rằng DKIM và SPF của mình được định cấu hình chính xác, bạn có thể cập nhật giá trị này thànhquarantine
để các nhà cung cấp tự động định tuyến các email bị lỗi đến thư mục spam hoặcreject
yêu cầu nhà cung cấp từ chối / trả lại các email không thành công. -
pct=100
cho biết tỷ lệ email không thành công mà hành động sẽ được áp dụng. -
rua=mailto:[email protected]
là địa chỉ email để gửi các báo cáo tổng hợp. Các báo cáo này chứa thông tin về tất cả các email từ các IP của bạn do một nhà cung cấp nhất định nhận được. Thay thế[email protected]
bằng địa chỉ email bạn muốn nhận các báo cáo đó.
Cách tạo Mẫu động trong SendGrid
Công cụ chúng ta sẽ xây dựng hôm nay sử dụng tính năng mẫu động của SendGrid để đặt chủ đề và nội dung của email. Để thiết lập điều này, hãy chọn tùy chọn "API Email" trong menu điều hướng bên, sau đó chọn "Mẫu động".
Bạn sẽ thấy màn hình có lời nhắc tạo mẫu động đầu tiên của mình. Chọn tùy chọn "Tạo Mẫu Động".
Đặt tên cho mẫu mới của bạn:"freeCodeCamp SendGrid Tutorial". SendGrid sẽ thêm mẫu này vào danh sách các mẫu có sẵn. Chọn mẫu để xem Template ID
(hãy ghi nhớ điều này, vì chúng tôi sẽ cần nó cho công cụ sau này) và nhấp vào nút "Thêm phiên bản".
Chọn "Mẫu trống" trên màn hình xuất hiện, sau đó chọn "Trình chỉnh sửa mã". Bây giờ bạn sẽ thấy chế độ xem trình chỉnh sửa. Trình soạn thảo của SendGrid sử dụng HTML để tạo nội dung email - tuy nhiên, khi chúng tôi xây dựng công cụ của mình, chúng tôi sẽ gửi phiên bản văn bản thuần túy.
Bây giờ, hãy thay thế nội dung của trình chỉnh sửa bằng mã sau:
<p>This is a test email used with the freeCodeCamp SendGrid tutorial</p>
<p>Unsubscribe: {{{unsubscribeId}}}</p>
Bạn sẽ nhận thấy rằng chúng tôi đã thêm {{{unsubscribeId}}}
. Mẫu của SendGrid sử dụng Handlebars để thay thế động các giá trị - chúng tôi sẽ tận dụng tính năng này khi chúng tôi xây dựng công cụ.
Bây giờ hãy chọn tùy chọn cài đặt từ trên cùng bên trái - bạn có thể tùy ý đặt tên cho phiên bản mẫu của mình, nhưng trường "Chủ đề" là những gì chúng tôi muốn sửa đổi. Đặt giá trị này thành {{{subject}}}
để tải động giá trị chủ đề từ công cụ của chúng tôi.
Để kiểm tra mẫu động, hãy chọn tùy chọn "Dữ liệu Kiểm tra" từ menu trên cùng. Chèn dữ liệu JSON này vào trình chỉnh sửa ở đó:
{
"unsubscribeId": "1",
"subject": "Testing emails!"
}
Bây giờ bạn sẽ thấy bản xem trước ở phía bên phải của màn hình phản ánh các giá trị này trong mẫu. Hãy nhớ nhấn Save
để lưu các thay đổi của bạn!
Cách tạo khóa API trong SendGrid
Bước cuối cùng trong việc định cấu hình tài khoản SendGrid của bạn là tạo khóa API để công cụ của chúng tôi sử dụng.
Nhấp vào mũi tên quay lại ở trên cùng bên trái để quay lại trang SendGrid chính. Sau đó chọn "Cài đặt" và "Khóa API". Chọn "Tạo khóa API" để tạo khóa mới. Bạn có thể tùy chọn cấp "Quyền truy cập đầy đủ" cho khóa của mình, nhưng với mục đích của hướng dẫn này, bạn sẽ chỉ cần quyền truy cập "Gửi thư".
Đảm bảo đặt tên mô tả cho khóa của bạn để bạn sẽ nhớ mục đích của nó nếu truy cập lại vào màn hình này. Khi bạn đã định cấu hình các quyền của mình, hãy chọn "Tạo và xem" để tạo khóa - lưu khóa này ở nơi an toàn vì bạn sẽ không thể xem lại .
Cách tạo Công cụ Email
Bây giờ là lúc viết mã để thực sự gửi một số email. Bạn có thể xem mã cho ứng dụng trực tiếp của chúng tôi, nhưng vì mục đích của hướng dẫn này, chúng tôi sẽ xây dựng một phiên bản rút gọn một chút để tập trung chủ yếu vào việc sử dụng API SendGrid.
Phần mềm Bắt buộc cho Tập lệnh Chiến dịch Email Tùy chỉnh
Bạn sẽ cần cài đặt các công cụ sau để làm việc với dự án này:
- Node.js - phiên bản LTS được khuyến nghị
- Một IDE, chẳng hạn như VSCode hoặc Atom
Bạn cũng có thể muốn git
tùy ý để kiểm soát phiên bản.
Công cụ trực tiếp của chúng tôi sử dụng một cụm MongoDB Atlas, nhưng ví dụ hướng dẫn của chúng tôi sẽ không. Nếu bạn chưa quen với MongoDB, chương trình học của freeCodeCamp bao gồm một phần tuyệt vời về cách thiết lập và sử dụng MongoDB.
Cách Khởi tạo Dự án
Tạo một thư mục (thư mục) để làm việc trong dự án này. Sau đó, mở thư mục đó bằng trình chỉnh sửa và thiết bị đầu cuối bạn chọn.
Để bắt đầu, chúng ta sẽ cần thiết lập dự án này như một dự án Node. Cách nhanh nhất để làm như vậy là với npm init
trong thiết bị đầu cuối của bạn. Phần này sẽ hướng dẫn bạn cách tạo package.json
là tệp cốt lõi của một ứng dụng Node.
Các giá trị mặc định sẽ hoạt động tốt cho ứng dụng của chúng tôi, nhưng chúng tôi sẽ muốn sửa đổi scripts
phần:
"scripts": {
"build": "tsc",
"send": "node ./prod/send.js"
},
npm init
sẽ tạo một test
script - điều này có thể bị xóa cho dự án của chúng tôi.
build
script sẽ được sử dụng để biên dịch TypeScript của chúng tôi thành JavaScript và send
script sẽ chạy ứng dụng của chúng tôi.
Tiếp theo chúng ta sẽ cài đặt và thiết lập TypeScript. Nếu bạn không quen thuộc với TypeScript, về cơ bản nó là một tập hợp siêu JavaScript với các định nghĩa kiểu mạnh hơn và kiểm tra lỗi thời gian biên dịch.
Để cài đặt TypeScript trên dự án của bạn, hãy chạy npm install --save-dev typescript
trong thiết bị đầu cuối của bạn. (--save-dev
cờ lưu nó dưới dạng phụ thuộc phát triển - TypeScript không bắt buộc trong thời gian chạy vì vậy có thể được dọn dẹp trong môi trường sản xuất).
TypeScript yêu cầu tệp cấu hình của riêng nó để thiết lập các quy tắc mà nó phải tuân theo khi tạo tệp JavaScript. Tạo một tệp trong thư mục gốc của dự án của bạn có tên là tsconfig.json
và chèn phần sau:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./prod",
"rootDir": "./src"
}
}
excludes
tài sản. Giá trị đó dành riêng cho cấu trúc tệp hướng dẫn và bạn sẽ không cần nó. Để ngắn gọn, chúng tôi sẽ không đi sâu vào các cài đặt cấu hình này. Nếu bạn muốn biết thêm thông tin, TypeScript có tài liệu rất chuyên sâu.
Nếu bạn đang sử dụng git
để kiểm soát phiên bản và tải nó lên một kho lưu trữ (chẳng hạn như GitHub), bạn sẽ muốn tạo một .gitignore
tệp trong thư mục gốc của dự án của bạn. Tệp này phải chứa:
/node_modules/
.env
/prod/
-
/node_modules/
sẽ bỏ qua các gói đã cài đặt. Đây được coi là phương pháp hay nhất khi làm việc với kiểm soát phiên bản. -
.env
sẽ bỏ qua tệp biến môi trường của chúng tôi. Điều này rất quan trọng vì bạn không bao giờ muốn cam kết những bí mật của bạn vào một kho lưu trữ. -
/prod/
sẽ bỏ qua các tệp JavaScript đã biên dịch của chúng tôi. Chúng tôi cũng sẽ sử dụng thư mục này cho danh sách email của mình, vì vậy, điều quan trọng là tránh vô tình sử dụng thông tin nhận dạng riêng tư đó.
Tạo .env
tệp trong thư mục dự án gốc của bạn. Chúng tôi sẽ tải các biến môi trường sau thông qua tệp này:
SENDGRID_API_KEY=
SENDGRID_FROM=
SENDGRID_TEMPLATE_ID=
MAIL_SUBJECT=
=
ký tên! -
SENDGRID_API_KEY
phải là khóa API mà bạn đã tạo ở các bước trước. -
SENDGRID_FROM
phải là địa chỉ email của bạn (đây là địa chỉ được sử dụng chofrom
trường). -
SENDGRID_TEMPLATE_ID
phải làid
chuỗi cho mẫu động bạn đã tạo trước đó. -
MAIL_SUBJECT
sẽ là dòng chủ đề cho các email bạn gửi. Bây giờ, hãy đặt đây là "Email hướng dẫn của fCC".
Cuối cùng, tạo src
trong thư mục dự án gốc của bạn và tạo một send.ts
tệp trong thư mục đó.
Cách cài đặt phần phụ thuộc của bạn
Trước tiên, chúng ta cần cài đặt sendgrid
Gói Node.js. Gói này đóng vai trò như một trình bao bọc cho API SendGrid và sẽ hợp lý hóa quy trình của chúng tôi để thực hiện các lệnh gọi API để gửi email. Chạy npm install @sendgrid/mail
để cài đặt gói này.
Sau đó, chúng ta cần một vài phụ thuộc phát triển. Chạy npm install --save-dev dotenv @types/node
.
-
dotenv
sẽ cho phép chúng tôi tải các biến môi trường từ.env
tệp cục bộ. -
@types/node
cung cấp các định nghĩa kiểu cho Node.js - TypeScript dựa vào các định nghĩa này để hiểu cấu trúc của các phương thức và chức năng tích hợp sẵn.
Cách viết logic
Bây giờ chúng tôi sẽ làm việc trong /src/send.ts
của chúng tôi tệp - đây là nơi chúng tôi đang xây dựng phần lớn logic ứng dụng của mình. Chúng tôi sẽ bắt đầu bằng cách nhập các giá trị bắt buộc từ các gói của chúng tôi.
Đầu tiên, chúng tôi muốn tải dotenv
đóng gói và phân tích cú pháp các biến môi trường của chúng tôi.
import dotenv from "dotenv";
dotenv.config();
dotenv
chỉ cần thiết cho phát triển cục bộ - hầu hết các máy chủ trực tuyến như Heroku và Repl.it có thể xử lý các biến môi trường một cách nguyên bản
dotenv.config()
cuộc gọi đọc .env
của chúng tôi tệp và tải các giá trị vào process.env
Đối tượng nút.
Tiếp theo, chúng tôi nhập các mô-đun cần thiết từ gói SendGrid:
import sgMail, { MailDataRequired } from "@sendgrid/mail";
sgMail
là trình bao bọc API chính và MailDataRequired
là định nghĩa kiểu mà chúng tôi sẽ cần.
Cuối cùng, chúng tôi nhập một số tính năng Node tích hợp sẵn để xử lý các tệp của chúng tôi:
import path from "path";
import { createWriteStream, readFile } from "fs";
-
path
sẽ được sử dụng để định vị các tệp danh sách email của chúng tôi bằng các đường dẫn tương đối -
fs
sẽ được sử dụng để đọc và ghi vào các tệp đó
Đã đến lúc bắt đầu xây dựng logic! Ứng dụng của chúng tôi dựa trên một số giá trị cần thiết được đặt trong .env
, vì vậy chúng ta cần bắt đầu bằng cách xác thực rằng các biến đó được đặt chính xác. Nếu thiếu bất kỳ nội dung nào, chúng tôi muốn ứng dụng của mình thoát sớm để tránh gặp lỗi khi chúng tôi gửi email.
// Here we check for a valid API key
const apiKey = process.env.SENDGRID_API_KEY;
if (!apiKey) {
console.error("Missing SendGrid Key");
process.exit(1);
}
// Here we check for a valid from address
const fromAddress = process.env.SENDGRID_FROM;
if (!fromAddress) {
console.error("Missing sender email address!");
process.exit(1);
}
// Here we check for a dynamic template ID
const sgTemplate = process.env.SENDGRID_TEMPLATE_ID;
if (!sgTemplate) {
console.error("Missing SendGrid Template ID");
process.exit(1);
}
// Here we check for the mail subject, but if it is missing
// we do not need to exit. Instead we use a fallback value.
const subjectValue = process.env.MAIL_SUBJECT || "Fallback value - check your env!";
||
cú pháp cho mã rằng nếu process.env.MAIL_SUBJECT
không xác định hoặc sai, hãy sử dụng chuỗi thay thế.
process.exit(1)
cuộc gọi bạn thấy trong mỗi lần kiểm tra điều kiện yêu cầu Node kết thúc quá trình (ứng dụng của chúng tôi) với mã thoát là 1
. Điều này cho thấy rằng ứng dụng của chúng tôi bị lỗi do một trong những lần kiểm tra này không thành công.
SendGrid yêu cầu chúng tôi đặt khóa API. Bên dưới logic biến môi trường của bạn, hãy thêm lệnh gọi hàm để đặt khóa.
// Here we set the SendGrid API key
sgMail.setApiKey(apiKey);
Trước khi tiếp tục, hãy tiếp tục và chạy npm run build
trong thiết bị đầu cuối của bạn - điều này sẽ tạo ra một prod
thư mục chứa JavaScript đã biên dịch của chúng tôi. Bây giờ bạn sẽ thấy cấu trúc tệp sau:
Tại thời điểm này, nếu bạn đang sử dụng git
bạn muốn rất chắc chắn rằng prod
thư mục sẽ không được cam kết với kho lưu trữ của bạn.
Trong prod
thư mục, tạo một validEmails.csv
tập tin. Ứng dụng của chúng tôi sẽ sử dụng tệp này để đọc danh sách email. Khởi tạo tệp với nội dung sau (thay thế [email protected]
với địa chỉ email thực của bạn):
email,unsubscribeId
[email protected],1
[email protected],2
.csv
tệp không có khoảng trắng xung quanh dấu phẩy.
Bây giờ chúng ta có thể viết mã để phân tích cú pháp này thành một danh sách email! Trong src/send.ts
của bạn tệp, thêm mã này:
// Here we concatenate our file path for the valid email file
const filePath = path.join(__dirname + "/../validEmails.csv");
// This is where we start reading the file!
readFile(filePath, "utf8", (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(data)
});
function
khai báo thay thế, nếu bạn thích.
Bây giờ nếu bạn chạy npm run build
và npm run send
bạn sẽ thấy nội dung của validEmail.csv
của chúng tôi tập tin trong thiết bị đầu cuối. Nếu bạn muốn, bạn có thể xem tiến trình hiện tại của chúng tôi cho đến thời điểm này.
Tuyệt quá! Bây giờ chúng ta cần phân tích chuỗi đó thành một mảng các đối tượng để chúng ta có thể lặp qua nó và xây dựng các thông điệp email của chúng ta. Cập nhật chức năng gọi lại của chúng tôi:
// This is where we start reading the file!
readFile(filePath, "utf8", (err, data) => {
if (err) {
console.error(err);
return;
}
// Here we parse the data into an object array
const emailList = data
.split("\n")
.slice(1)
.map((el) => {
const [email, unsubscribeId] = el.split(",");
return { email, unsubscribeId };
});
});
[email, unsubscribeId]
áp dụng cấu trúc hủy để gán các giá trị của mảng tách cho hai biến đó. -
.split("\n")
chia chuỗi theo ngắt dòng. LƯU Ý :Nếu bạn đang sử dụng Windows, bạn có thể cần thay đổi cài đặt cuối dòng chovalidEmails.csv
của mình từCRLF
thànhLF
(Windows chèn thêm các ký tự ngắt dòng sẽ ảnh hưởng đến việc xử lý dữ liệu của chúng tôi) -
.slice(1)
loại bỏ phần tử đầu tiên của mảng đó (email,unsubscribeId
của chúng tôi dòng). -
map
của chúng tôi hàm sẽ chuyển đổi từngemail,unsubscribeId
chuỗi thành một{email, unsubscribeId}
đối tượng.
Kết quả cuối cùng của hàm phân tích cú pháp này sẽ là một mảng các đối tượng có email
và unsubscribeId
thuộc tính - làm việc với chuỗi trơn tru hơn nhiều.
Bây giờ là lúc để gửi một số email. Bên dưới chức năng phân tích cú pháp của bạn (nhưng vẫn nằm trong readFile
callback) thêm cấu trúc cho phương thức lặp của chúng tôi. Bởi vì chúng tôi muốn truy cập từng giá trị trong mảng, chúng tôi sẽ sử dụng .forEach
cách tiếp cận.
// Here we iterate through the emailList array
emailList.forEach((user) => {});
user
tham số sẽ là {email, unsubscribeId}
sự vật. Chúng tôi đã gọi nó là user
vì nó đại diện cho một đối tượng dữ liệu người dùng freeCodeCamp trong ứng dụng đầy đủ.
Trong lệnh gọi lại cho .forEach
, chúng ta có thể xây dựng đối tượng thông báo mà API SendGrid mong đợi.
// Here we iterate through the emailList array
emailList.forEach((user) => {
// This is the message object SendGrid needs
const message: MailDataRequired = {
to: user.email,
from: fromAddress,
subject: subjectValue,
text: "This goes away!",
templateId: sgTemplate,
dynamicTemplateData: {
subject: subjectValue,
unsubscribeId: user.unsubscribeId
}
}
});
Trước khi tiếp tục, chúng ta hãy xem xét kỹ hơn đối tượng tin nhắn này. MailDataRequired
chúng tôi đã nhập trước đó được sử dụng làm định nghĩa kiểu ở đây, vì vậy TypeScript có thể cảnh báo cho chúng tôi nếu chúng tôi tình cờ bỏ lỡ một thuộc tính bắt buộc. Rất may, chúng tôi có tất cả các thuộc tính cần thiết. Nhưng chúng có nghĩa là gì?
-
to:
Địa chỉ email để gửi tin nhắn. Đây sẽ làemail
từ mỗi dòng trongvalidEmails.csv
của chúng tôi tệp -
from:
Địa chỉ email để gửi tin nhắn. Điều này được đặt trong.env
của chúng tôi sớm hơn (nó phải là của bạn địa chỉ email). -
subject:
Trường này không bắt buộc nhưng cung cấp cho chúng tôi giá trị dự phòng trong trường hợp mẫu động không phân tích cú pháp chính xác chủ đề của chúng tôi. -
text:
Giá trị văn bản này được ghi đè bởi mẫu. Tuy nhiên, điều quan trọng vẫn là sử dụng. SendGrid có thể gửi email dưới dạngplaintext
hoặchtml
- bằng cách sử dụngtext
thay vìhtml
thuộc tính này, chúng tôi đảm bảo mẫu của chúng tôi được gửi dưới dạngplaintext
. Các nhà cung cấp email có nhiều khả năng hơn để gắn cờ các thư HTML là spam, vì vậy điều này giúp tăng tỷ lệ phân phối của chúng tôi. -
templateId:
Đây là ID cho mẫu động mà SendGrid sẽ sử dụng trong email. -
dynamicTemplateData:
Đây là những giá trị tương ứng với chuỗi Handlebars mà chúng tôi đã đặt trong mẫu động trước đó.
Tuyệt quá! Bước tiếp theo của chúng tôi là lấy thông điệp đã xây dựng này và gửi nó. Bên dưới đối tượng thông báo (nhưng vẫn nằm trong .forEach
gọi lại), hãy thêm cuộc gọi gửi của chúng tôi:
// Here we send the message we just constructed!
sgMail.send(message);
Thao tác này sẽ gửi thông báo đến từng email trong validEmails.csv
của chúng tôi . Thật không may, mã của chúng tôi sẽ chạy âm thầm và chúng tôi sẽ không biết liệu mỗi lần gửi có thành công hay không. Hãy thêm một số xử lý lỗi.
.send()
cuộc gọi trả về một Lời hứa, vì vậy chúng ta có thể sử dụng .then().catch()
để xử lý việc trả lại.
// Here we send the message we just constructed!
sgMail.send(message)
.then(() => {
// Here we log successful send requests
console.info(`Message send success: ${user.email}`)
}).catch((err) => {
// Here we log errored send requests
console.error(err);
console.error(`Message send failed: ${user.email}`)
});
Bây giờ nếu bạn chạy npm run build
và npm run send
bạn sẽ thấy một email đẹp trong hộp thư đến của mình!
Tại thời điểm này, bạn đã có một ứng dụng gửi email chức năng. Xin chúc mừng! Bạn có thể xem tiến trình của chúng tôi cho đến thời điểm này nếu bạn muốn.
Đọc tiếp để biết cách xử lý các email bị trả lại và logic bổ sung cho các lỗi gửi, đó là những gì chúng ta sẽ thảo luận tiếp theo.
Cách xử lý email bị trả lại trong SendGrid
Bạn có thể nhận thấy rằng [email protected]
rất nhiều không phải là một địa chỉ email thực. SendGrid sẽ tạo báo cáo bị trả lại hàng ngày cho hoạt động của bạn vào ngày hôm trước.
Mọi email bị trả lại đều làm tổn hại đến danh tiếng SendGrid của bạn và có thể dẫn đến việc các nhà cung cấp dịch vụ email đánh dấu thư của bạn là thư rác. Vì vậy, chúng tôi cần thêm logic để ngăn việc gửi đến các địa chỉ bị trả lại đã biết.
Bắt đầu bằng cách tạo bouncedEmails.csv
tệp trong prod
của bạn thư mục (nó phải ở bên cạnh validEmails.csv
của bạn ). Chúng tôi không cần unsubscribeId
ở đây, vì vậy hãy khởi tạo nó bằng:
email
[email protected]
Bây giờ quay lại send.ts
của chúng tôi tập tin. Trên dòng 38, ngay bên dưới filePath
hiện có của chúng tôi khai báo, định cấu hình đường dẫn cho bouncedEmails.csv
mới tệp.
// Here we concatenate our file paths for the CSV files
const filePath = path.join(__dirname + "/validEmails.csv");
const bouncePath = path.join(__dirname + "/bouncedEmails.csv");
send.ts
tệp).
Tuyệt quá! Bây giờ chúng ta cần đọc tệp đó. Ngay bên dưới các khai báo đường dẫn tệp này (trước readFile
hiện có của chúng tôi gọi), thêm logic để đọc các tệp bị trả lại.
// Read through the bounce list, parse into array
readFile(bouncePath, "utf8", (err, data) => {
if (err) {
console.error(err);
process.exit(1);
}
bounceList = data.split("\n").slice(1);
readFile
là không đồng bộ - vì vậy chúng tôi cần bao bọc hàm gọi lại xung quanh tất cả logic gửi hiện có của chúng tôi . Đảm bảo rằng })
đóng của bạn cho lệnh gọi lại này được chuyển đến cuối tệp của chúng tôi.
Chúng tôi đọc bouncedEmails.csv
, hãy tách nó trên dòng mới (hãy nhớ rằng bạn sẽ cần đảm bảo phần cuối dòng của mình là LF
) và xóa email
hàng. Cuối cùng, chúng tôi tiếp tục với logic gửi hiện có của mình.
Quay lại logic gửi của chúng tôi. Trong .forEach
của chúng tôi , thêm logic để bỏ qua các email bị chặn (chúng tôi sẽ thêm điều này trước khi xây dựng đối tượng message để tránh tạo ra các biến không cần thiết).
// Here we iterate through the emailList array
emailList.forEach((user) => {
// Here we check if the email has been bounced
if (bounceList.length && bounceList.includes(user.email)) {
console.info(`Message send skipped: ${user.email}`);
return;
}
bounceList.csv
của chúng tôi tệp trống, đang gọi includes
sẽ ném ra một lỗi. Vì vậy, chúng tôi kiểm tra .length
giá trị đầu tiên.
Bằng cách tận dụng return
sớm tuyên bố, chúng tôi kết thúc .forEach
cụ thể đó lặp lại khi bounceList
bao gồm email đó. Điều này ngăn chúng tôi cố gắng gửi đến các địa chỉ email đã bị trả lại trước đó. Bây giờ nếu bạn chạy npm run build
và npm run start
, bạn sẽ thấy đầu ra này trong thiết bị đầu cuối của mình:
Xem tiến trình của chúng tôi cho đến thời điểm này.
Cách chụp các email không thành công trong SendGrid
Hiện tại ứng dụng của chúng tôi sẽ báo lỗi nếu không gửi được email. Điều này có thể hoạt động đối với các trường hợp sử dụng nhỏ, nhưng khi mở rộng ứng dụng, bạn sẽ ngày càng khó xác định những lỗi đó và cố gắng gửi lại.
Nhưng thay vào đó, chúng tôi có thể làm cho ứng dụng của mình lưu những email đó vào một tệp mới.
Tạo failedEmails.csv
tệp trong prod
của bạn thư mục. Tệp này có thể trống. Chúng tôi sẽ viết mã để thêm hàng tiêu đề.
Quay lại send.ts
của chúng tôi tệp, hãy chuyển đến phần khai báo đường dẫn của chúng tôi trên dòng 38. Hãy thêm một phần khai báo nữa cho failedEmails.csv
mới của chúng tôi :
// Here we concatenate our file paths for the CSV files
const filePath = path.join(__dirname + "/validEmails.csv");
const bouncePath = path.join(__dirname + "/bouncedEmails.csv");
const failedPath = path.join(__dirname + "/failedEmails.csv");
Không giống như các đường dẫn khác của chúng tôi, đường dẫn này sẽ được sử dụng cho write
hoạt động. Bởi vì chúng tôi muốn viết liên tục khi email được xử lý, chúng tôi cần tạo một luồng để làm như vậy. Ngay bên dưới các khai báo đường dẫn này, hãy tạo luồng đó và thêm hàng tiêu đề ban đầu của chúng ta.
// Here we create our write stream for failed emails
const failedStream = createWriteStream(failedPath);
// Here we add the header row
failedStream.write("email,unsubscribeId\n")
Đã đến lúc cải thiện logic xử lý lỗi của chúng tôi để kết hợp luồng mới này. Chúng tôi cần thêm một write
khác thao tác xử lý lỗi của chúng tôi trong send
cuộc gọi.
// Here we send the message we just constructed!
sgMail
.send(message)
.then(() => {
// Here we log successful send requests
console.info(`Message send success: ${user.email}`);
})
.catch((err) => {
// Here we log errored send requests
console.error(err);
console.error(`Message send failed: ${user.email}`);
// And here we add that email to the failedEmails.csv
failedStream.write(`${user.email},${user.unsubscribeId}\n`)
});
Điều này sẽ viết email
và unsubscribeId
sang failedEmails.csv
mới của chúng tôi ở định dạng thích hợp - cho phép chúng tôi sao chép dữ liệu đó vào validEmails.csv
để thực hiện một lần gửi khác.
Xin chúc mừng! Bây giờ bạn đã xây dựng một công cụ thành công và đầy đủ chức năng để gửi các vụ nổ email. Bạn có thể xem mã hoàn thành nếu bạn muốn xác nhận công việc của mình. Nhưng hãy tiếp tục đọc để biết một vài tính năng tùy chọn, "rất vui khi có".
Các tính năng tùy chọn cho Công cụ Email của bạn
Vì công cụ của chúng tôi dựa trên CLI (có nghĩa là nó được sử dụng trong giao diện dòng lệnh hoặc thiết bị đầu cuối) nên không có nhiều phản hồi của người dùng. Chúng tôi có thể tận dụng một số chức năng bảng điều khiển bổ sung để cung cấp thêm thông tin về tiến trình của tập lệnh.
Hãy bắt đầu bằng cách thêm một số "trạm kiểm soát". Trước khi xác thực biến môi trường của chúng ta, hãy in một thông báo rằng tập lệnh đã bắt đầu và đang kiểm tra các biến:
console.info('Script started. Validating environment variables...')
Sau đó, sau khi xác thực, chúng tôi có thể in một thông báo thành công.
// Here we set the SendGrid API key
sgMail.setApiKey(apiKey);
console.info('Variables confirmed!')
Trong chức năng đọc tệp bị trả lại của chúng tôi, chúng tôi có thể thêm một số thông báo để bắt đầu, thất bại và thành công.
console.info('Reading bounced email list...')
// Read through the bounce list, parse into array
readFile(bouncePath, "utf8", (err, data) => {
if (err) {
console.error(err);
console.error('Failed to read bounced emails!')
process.exit(1);
}
bounceList = data.split("\n").slice(1);
console.info('Bounced emails read!')
Và tương tự đối với danh sách email hợp lệ của chúng tôi:
console.info('Reading send list...')
// This is where we start reading the file!
readFile(filePath, "utf8", (err, data) => {
if (err) {
console.error(err);
console.error('Failed to read send list!')
return;
}
Bây giờ, sẽ rất tuyệt nếu có một bản in tin nhắn khi hoạt động hoàn tất. Tuy nhiên, nếu chúng ta thêm console.info
sau .forEach
của chúng tôi vòng lặp, nó sẽ thực sự in trước khi email đã gửi xong!
Điều này là do .send
phương thức tạo một cuộc gọi mạng và trả về một Lời hứa và Lời hứa đó có thể chưa được giải quyết / từ chối trước khi quá trình lặp lại của chúng ta kết thúc.
Vì vậy, thay vào đó, chúng ta có thể xây dựng một bộ đếm để theo dõi số lượng email chúng tôi đã gửi so với tổng số email. Ngay trước .forEach
của chúng tôi lặp lại, thêm các biến sau:
// Here we create variables for counting
const emailTotal = emailList.length;
let emailCount = 0;
Chúng tôi muốn đếm các email bị trả lại là đã được xử lý, ngay cả khi chúng tôi đang bỏ qua chúng.
// Here we iterate through the emailList array
emailList.forEach((user) => {
// Here we check if the email has been bounced
if (bounceList.includes(user.email)) {
console.info(`Message send skipped: ${user.email}`);
emailCount++;
if (emailCount === emailTotal) {
console.info(
`Sending complete! Sent ${emailTotal} emails. Have a nice day!`
);
return;
}
}
Cuối cùng chúng ta cần thêm logic để xem email chúng ta đã gửi có phải là email cuối cùng hay không. Logic này áp dụng cho thành công của chúng tôi và các trình xử lý lỗi cho cuộc gọi gửi:
// Here we send the message we just constructed!
sgMail
.send(message)
.then(() => {
// Here we log successful send requests
console.info(`Message send success: ${user.email}`);
// Here we handle the email counts
emailCount++;
if (emailCount === emailTotal) {
console.info(
`Sending complete! Sent ${emailTotal} emails. Have a nice day!`
);
}
})
.catch((err) => {
// Here we log errored send requests
console.error(err);
console.error(`Message send failed: ${user.email}`);
// And here we add that email to the failedEmails.csv
failedStream.write(`${user.email},${user.unsubscribeId}\n`);
// Here we handle the email counts
emailCount++;
if (emailCount === emailTotal) {
console.info(
`Sending complete! Sent ${emailTotal} emails. Have a nice day!`
);
}
});
Và với điều đó, ứng dụng của chúng tôi đã hoàn chỉnh! Nếu bạn chạy npm run build
và npm run send
tập lệnh, bạn sẽ thấy đầu ra này trong thiết bị đầu cuối của mình:
Và bạn hẳn đã nhận được một vài email giống như sau:
Bạn có thể xem mã cuối cùng của chúng tôi tại đây hoặc bạn có thể xem phiên bản mở rộng được xây dựng cho freeCodeCamp.