เป็นเวลาหลายปีที่ Quincy Larson ส่งจดหมายข่าวทางอีเมลรายสัปดาห์ผ่านแพลตฟอร์ม Mail for Good ของ freeCodeCamp ซึ่งขับเคลื่อนโดย Amazon SES
เขาเพิ่งย้ายกระบวนการนี้ไปยัง SendGrid ในบทความนี้ ผมจะแสดงให้คุณเห็นถึงวิธีการสร้างเครื่องมือเพื่อให้บรรลุสิ่งนี้
วิธีตั้งค่าบัญชี SendGrid
ขั้นตอนแรกคือการลงทะเบียน SendGrid และตั้งค่าบัญชีของคุณ สำหรับจุดประสงค์ของบทช่วยสอนนี้ ระดับฟรีควรเพียงพอ
เมื่อคุณขยายขนาดแอปพลิเคชัน คุณอาจต้องเพิ่มขีดจำกัดอีเมลที่ใช้ได้ผ่านแพลตฟอร์ม
วิธีตั้งค่าที่อยู่ IP เฉพาะบน SendGrid
ตามค่าเริ่มต้น SendGrid จะใช้ที่อยู่ IP ที่ใช้ร่วมกันสำหรับการส่งอีเมล นี่อาจเป็นที่ยอมรับสำหรับแอปพลิเคชันอีเมลขนาดเล็ก แต่เมื่อคุณเพิ่มอัตราการส่ง คุณจะต้องตั้งค่าที่อยู่ IP เฉพาะ
นี่เป็นความคิดที่ดี เนื่องจาก "ชื่อเสียงของผู้ส่ง" ของคุณ (เมตริกที่ SendGrid ใช้ในการประเมินสถานะของคุณกับผู้ให้บริการอีเมล) จะไม่ได้รับผลกระทบในทางลบจากการกระทำของผู้ใช้รายอื่นที่ใช้ IP เดียวกัน
ในการตั้งค่า IP เฉพาะของคุณเอง ให้เลือกตัวเลือก "การตั้งค่า" จากเมนูการนำทางด้านข้าง จากนั้นเลือก "ที่อยู่ IP" อย่างไรก็ตาม โปรดทราบว่าตัวเลือกนี้ไม่มีให้บริการในระดับฟรี
คุณอาจมีที่อยู่ IP เฉพาะที่ตั้งค่าไว้แล้ว ทั้งนี้ขึ้นอยู่กับแผนการชำระเงินของคุณ หากคุณไม่มีหรือเลือกที่จะเพิ่ม คุณสามารถเลือกปุ่ม "เพิ่มที่อยู่ IP" เพื่อกำหนดค่า IP ใหม่ได้
วิธีการอนุญาตผู้ส่งอีเมลใน SendGrid
หมายเหตุ:คุณสามารถข้ามส่วนนี้ได้หากคุณใช้โดเมนที่กำหนดเองสำหรับอีเมลของคุณ
ในการส่งอีเมลจากที่อยู่อีเมลส่วนตัวของคุณ คุณจะต้องยืนยันว่าที่อยู่อีเมลนั้นเป็นของคุณ
ในเมนูด้านซ้าย เลือก "การตั้งค่า" จากนั้นเลือก "การตรวจสอบผู้ส่ง" เลือก "ยืนยันผู้ส่งรายเดียว" เพื่ออธิบายขั้นตอนการเพิ่มที่อยู่อีเมลของคุณ
วิธีการตรวจสอบโดเมนที่กำหนดเองของคุณใน SendGrid
หมายเหตุ:คุณสามารถข้ามส่วนนี้ได้หากคุณไม่ได้ใช้โดเมนที่กำหนดเองสำหรับอีเมลของคุณ
ในการส่งอีเมลจากโดเมนอีเมลที่กำหนดเอง คุณจะต้องตรวจสอบสิทธิ์โดเมนนั้นด้วย SendGrid หากต้องการไปที่หน้าจอนี้ ให้เลือกเมนูการตั้งค่าอีกครั้ง จากนั้นเลือก "การตรวจสอบผู้ส่ง"
จากนั้นคุณควรเห็นหน้าจอที่มีตัวเลือกสำหรับ "Domain Authentication" เลือกตัวเลือก "รับรองความถูกต้องโดเมนของคุณ" แล้ว SendGrid จะแนะนำขั้นตอนการกำหนดค่าระเบียน DNS ของคุณ (พร้อมคำแนะนำเฉพาะตามผู้ให้บริการ DNS ของคุณ)
วิธีการตั้งค่า Reverse DNS ใน SendGrid
หมายเหตุ:คุณสามารถข้ามส่วนนี้ได้หากคุณไม่ได้ใช้โดเมนที่กำหนดเองสำหรับอีเมลของคุณ
Reverse DNS (Domain Name System) ถูกใช้โดยผู้ให้บริการอีเมลเพื่อค้นหาเจ้าของที่อยู่ IP ที่ระบุ การตั้งค่านี้จะช่วยให้ผู้ให้บริการอีเมลสามารถตรวจสอบว่าที่อยู่ IP ที่คุณส่งอีเมลนั้นเชื่อมต่อกับโดเมนที่คุณกำหนดเอง
ในหน้าจอการตรวจสอบผู้ส่งเดียวกันกับด้านบน คุณจะเห็นส่วน "Reverse DNS" จะมีตัวเลือกในการกำหนดค่า DNS แบบย้อนกลับสำหรับ IP เฉพาะแต่ละรายการที่คุณมีในบัญชีของคุณ เช่น การตรวจสอบโดเมน แพลตฟอร์มของ SendGrid จะแนะนำคุณตลอดการตั้งค่า
วิธีตั้งค่าการตรวจสอบสิทธิ์อีเมลใน SendGrid
หมายเหตุ:คุณสามารถข้ามส่วนนี้ได้หากคุณไม่ได้ใช้โดเมนที่กำหนดเองสำหรับอีเมลของคุณ
ผู้ให้บริการอีเมลรายใหญ่ (เช่น Gmail, Yahoo และ Outlook) ใช้หลายวิธีในการตรวจสอบสิทธิ์ผู้ส่งอีเมล:SPF, DKIM และ DMARC
- SPF (กรอบนโยบายผู้ส่ง) ตรวจสอบว่าที่อยู่ IP ที่ส่งอีเมลจากโดเมนของคุณได้รับอนุญาตให้ทำเช่นนั้น
- DKIM (DomainKeys Identified Mail) ใช้สตริงคีย์สาธารณะเพื่อตรวจสอบว่าอีเมล
from
ที่อยู่ถูกต้องและไม่ปลอมแปลง/ปลอมแปลง - DMARC (Domain-based Message Authentication, Reporting and Conformance) คือชุดคำสั่งที่บอกผู้ให้บริการอีเมลถึงวิธีตอบสนองเมื่ออีเมลไม่ผ่านการตรวจสอบ SPF หรือ DKIM
ขั้นตอนการตรวจสอบสิทธิ์ของ SendGrid จะแนะนำคุณตลอดการตั้งค่า SPF และ DKIM โดยเป็นส่วนหนึ่งของกระบวนการตรวจสอบสิทธิ์โดเมน แต่คุณจะต้องกำหนดค่า DMARC ด้วยตนเอง
ไปที่ผู้ให้บริการโฮสต์ DNS ของคุณและเข้าถึงการตั้งค่าการจัดการ DNS จากนั้นเพิ่ม TXT
. ใหม่ บันทึกชื่อ _dmarc.yourdomain.com
(แทนที่ yourdomain.com
ด้วยโดเมนที่คุณกำหนดเอง)
โปรดทราบว่าผู้ให้บริการบางราย เช่น GoDaddy จะเพิ่มโดเมนของคุณต่อท้ายระเบียนโดยอัตโนมัติ ในกรณีนี้ ชื่อควรเป็น _dmarc
.
ค่า ของบันทึกนี้ควรมีโครงสร้างคล้ายกับ:
"v=DMARC1; p=none; pct=100; rua=mailto:[email protected]"
v=DMARC
ระบุเวอร์ชันของกฎ DMARC ที่จะใช้ (ปัจจุบันมีเฉพาะเวอร์ชัน 1 เท่านั้น)p=none
ระบุการดำเนินการที่ผู้ให้บริการอีเมลควรทำเมื่ออีเมลล้มเหลวใน DKIM หรือ SPF การตั้งค่านี้ควรเริ่มต้นเป็นnone
เพื่อหลีกเลี่ยงผลกระทบต่อการส่งอีเมลของคุณ เมื่อคุณยืนยันว่า DKIM และ SPF ได้รับการกำหนดค่าอย่างถูกต้องแล้ว คุณสามารถอัปเดตค่านี้เป็นquarantine
เพื่อให้ผู้ให้บริการกำหนดเส้นทางอีเมลที่ล้มเหลวไปยังโฟลเดอร์สแปมโดยอัตโนมัติ หรือreject
เพื่อให้ผู้ให้บริการปฏิเสธ/ตีกลับอีเมลที่ล้มเหลวpct=100
ระบุเปอร์เซ็นต์ของอีเมลที่ล้มเหลวซึ่งควรดำเนินการrua=mailto:[email protected]
คือที่อยู่อีเมลที่จะส่งรายงานรวมไป รายงานเหล่านี้มีข้อมูลเกี่ยวกับอีเมลทั้งหมดจาก IP ของคุณที่ได้รับจากผู้ให้บริการรายใดรายหนึ่ง แทนที่[email protected]
ด้วยที่อยู่อีเมลที่คุณต้องการรับรายงานเหล่านั้น
วิธีสร้างเทมเพลตแบบไดนามิกใน SendGrid
เครื่องมือที่เราจะสร้างในวันนี้ใช้คุณลักษณะเทมเพลตแบบไดนามิกของ SendGrid เพื่อกำหนดหัวเรื่องและเนื้อหาของอีเมล ในการตั้งค่านี้ ให้เลือกตัวเลือก "Email API" ในเมนูการนำทางด้านข้าง จากนั้นเลือก "เทมเพลตไดนามิก"
คุณจะเห็นหน้าจอพร้อมท์ให้สร้างเทมเพลตไดนามิกแรกของคุณ เลือกตัวเลือก "สร้างเทมเพลตแบบไดนามิก"
ตั้งชื่อเทมเพลตใหม่ของคุณ:"freeCodeCamp SendGrid Tutorial" SendGrid จะเพิ่มเทมเพลตนี้ในรายการเทมเพลตที่พร้อมใช้งาน เลือกเทมเพลตเพื่อดู Template ID
(จดบันทึกสิ่งนี้ เนื่องจากเราต้องการเครื่องมือนี้ในภายหลัง) และคลิกปุ่ม "เพิ่มเวอร์ชัน"
เลือก "เทมเพลตเปล่า" บนหน้าจอที่ปรากฏขึ้น จากนั้นเลือก "ตัวแก้ไขโค้ด" ตอนนี้คุณควรเห็นมุมมองเอดิเตอร์ โปรแกรมแก้ไขของ SendGrid ใช้ HTML เพื่อสร้างเนื้อหาอีเมล อย่างไรก็ตาม เมื่อเราสร้างเครื่องมือ เราจะส่งเวอร์ชันข้อความธรรมดา
ในตอนนี้ ให้แทนที่เนื้อหาของตัวแก้ไขด้วยรหัสต่อไปนี้:
<p>This is a test email used with the freeCodeCamp SendGrid tutorial</p>
<p>Unsubscribe: {{{unsubscribeId}}}</p>
คุณจะสังเกตเห็นว่าเราได้เพิ่ม {{{unsubscribeId}}}
. เทมเพลตของ SendGrid ใช้ Handlebars เพื่อแทนที่ค่าแบบไดนามิก - เราจะใช้ประโยชน์จากคุณลักษณะนี้เมื่อเราสร้างเครื่องมือ
ตอนนี้ เลือกตัวเลือกการตั้งค่าจากด้านซ้ายบน - คุณอาจเลือกตั้งชื่อเวอร์ชันเทมเพลตของคุณได้ แต่ช่อง "หัวเรื่อง" คือสิ่งที่เราต้องการแก้ไข ตั้งค่านี้เป็น {{{subject}}}
เพื่อโหลดค่าหัวเรื่องจากเครื่องมือของเราแบบไดนามิก
หากต้องการทดสอบเทมเพลตแบบไดนามิก ให้เลือกตัวเลือก "ทดสอบข้อมูล" จากเมนูด้านบน แทรกข้อมูล JSON นี้ลงในตัวแก้ไขที่นั่น:
{
"unsubscribeId": "1",
"subject": "Testing emails!"
}
ตอนนี้คุณควรเห็นการแสดงตัวอย่างทางด้านขวาของหน้าจอซึ่งแสดงถึงค่าเหล่านี้ในเทมเพลต อย่าลืมกด Save
ปุ่มเพื่อบันทึกการเปลี่ยนแปลงของคุณ!
วิธีสร้างคีย์ API ใน SendGrid
ขั้นตอนสุดท้ายในการกำหนดค่าบัญชี SendGrid คือการสร้างคีย์ API เพื่อให้เครื่องมือของเราใช้งานได้
คลิกลูกศรย้อนกลับที่ด้านบนซ้ายเพื่อกลับไปยังหน้า SendGrid หลัก จากนั้นเลือก "การตั้งค่า" และ "คีย์ API" เลือก "สร้างคีย์ API" เพื่อสร้างคีย์ใหม่ คุณสามารถเลือกให้ "การเข้าถึงแบบเต็ม" กับคีย์ของคุณได้ แต่สำหรับจุดประสงค์ของบทช่วยสอนนี้ คุณจะต้องเข้าถึง "ส่งเมล" เท่านั้น
อย่าลืมตั้งชื่อที่สื่อความหมายให้กับคีย์ของคุณ เพื่อที่คุณจะจดจำจุดประสงค์ของคีย์ได้หากคุณเข้าถึงหน้าจอนี้อีกครั้ง เมื่อคุณกำหนดค่าการอนุญาตแล้ว ให้เลือก "สร้างและดู" เพื่อสร้างคีย์ - บันทึกไว้ในที่ที่ปลอดภัยเพราะคุณจะไม่สามารถดูได้อีก .
วิธีสร้างเครื่องมืออีเมล
ตอนนี้ได้เวลาเขียนโค้ดเพื่อส่งอีเมลจริงๆ แล้ว คุณสามารถดูโค้ดสำหรับแอปพลิเคชันที่ใช้งานจริงได้ แต่สำหรับจุดประสงค์ของบทช่วยสอนนี้ เราจะสร้างเวอร์ชันที่ลดขนาดลงเล็กน้อยเพื่อเน้นที่การใช้ SendGrid API เป็นหลัก
ซอฟต์แวร์ที่จำเป็นสำหรับสคริปต์แคมเปญอีเมลที่กำหนดเอง
คุณจะต้องติดตั้งเครื่องมือต่อไปนี้เพื่อใช้งานโปรเจ็กต์นี้:
- Node.js - แนะนำให้ใช้เวอร์ชัน LTS
- IDE เช่น VSCode หรือ Atom
คุณยังอาจต้องการ git
สำหรับการควบคุมเวอร์ชัน
เครื่องมือสดของเราใช้คลัสเตอร์ MongoDB Atlas แต่ตัวอย่างบทช่วยสอนของเราจะไม่ใช้ หากคุณไม่คุ้นเคยกับ MongoDB หลักสูตรของ freeCodeCamp จะมีส่วนที่ยอดเยี่ยมในการตั้งค่าและใช้งาน MongoDB
วิธีการเริ่มต้นโครงการ
สร้างไดเร็กทอรี (โฟลเดอร์) ที่จะใช้ในโครงการนี้ จากนั้นเปิดโฟลเดอร์นั้นด้วยเครื่องมือแก้ไขและเทอร์มินัลที่คุณเลือก
ในการเริ่มต้น เราจะต้องตั้งค่านี้เป็นโปรเจ็กต์โหนด วิธีที่เร็วที่สุดคือใช้ npm init
ในเทอร์มินัลของคุณ ขั้นตอนนี้จะแนะนำคุณเกี่ยวกับการสร้าง package.json
ซึ่งเป็นไฟล์หลักของแอปพลิเคชันโหนด
ค่าเริ่มต้นจะทำงานได้ดีสำหรับแอปพลิเคชันของเรา แต่เราจะต้องการแก้ไข scripts
ส่วน:
"scripts": {
"build": "tsc",
"send": "node ./prod/send.js"
},
npm init
จะสร้าง test
สคริปต์ - สามารถลบออกสำหรับโครงการของเราได้
The build
สคริปต์จะถูกใช้เพื่อรวบรวม TypeScript ของเราเป็น JavaScript และ send
สคริปต์จะเรียกใช้แอปพลิเคชันของเรา
ต่อไปเราจะติดตั้งและตั้งค่า TypeScript หากคุณไม่คุ้นเคยกับ TypeScript มันจะเป็น superset ของ JavaScript ที่มีคำจำกัดความประเภทที่เข้มงวดกว่าและการตรวจสอบข้อผิดพลาดในการคอมไพล์
ในการติดตั้ง TypeScript ในโครงการของคุณ ให้เรียกใช้ npm install --save-dev typescript
ในเทอร์มินัลของคุณ (The --save-dev
แฟล็กบันทึกเป็นการพึ่งพาการพัฒนา - ไม่จำเป็นต้องใช้ TypeScript ที่รันไทม์ จึงสามารถล้างข้อมูลในสภาพแวดล้อมที่ใช้งานจริงได้)
TypeScript ต้องการไฟล์การกำหนดค่าของตัวเองเพื่อตั้งกฎที่ควรปฏิบัติตามเมื่อสร้างไฟล์ JavaScript สร้างไฟล์ในไดเรกทอรีรากของโปรเจ็กต์ชื่อ tsconfig.json
และใส่ข้อความต่อไปนี้:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./prod",
"rootDir": "./src"
}
}
excludes
พิเศษ คุณสมบัติ. ค่านั้นเฉพาะสำหรับโครงสร้างไฟล์บทช่วยสอน และคุณไม่จำเป็นต้องใช้เพื่อความกระชับ เราจะไม่ลงลึกในการตั้งค่าการกำหนดค่าเหล่านี้ หากคุณต้องการข้อมูลเพิ่มเติม TypeScript มีเอกสารเชิงลึก
หากคุณกำลังใช้ git
สำหรับการควบคุมเวอร์ชันและการอัปโหลดไปยังที่เก็บ (เช่น GitHub) คุณจะต้องสร้าง .gitignore
ไฟล์ในไดเร็กทอรีรากของโปรเจ็กต์ของคุณ ไฟล์นี้ควรมี:
/node_modules/
.env
/prod/
/node_modules/
จะละเว้นแพ็คเกจที่ติดตั้ง นี่เป็นแนวทางปฏิบัติที่ดีที่สุดเมื่อทำงานกับการควบคุมเวอร์ชัน.env
จะละเว้นไฟล์ตัวแปรสภาพแวดล้อมของเรา สิ่งนี้สำคัญมากเพราะคุณไม่เคย ต้องการเปิดเผยความลับของคุณไปยังที่เก็บ/prod/
จะละเว้นไฟล์ JavaScript ที่คอมไพล์ของเรา นอกจากนี้ เราจะใช้โฟลเดอร์นี้สำหรับรายชื่ออีเมลของเรา ดังนั้นสิ่งสำคัญคือต้องหลีกเลี่ยงการเปิดเผยข้อมูลส่วนตัวที่สามารถระบุตัวตนได้โดยไม่ได้ตั้งใจ
สร้าง .env
ไฟล์ในไดเร็กทอรีโปรเจ็กต์รูทของคุณ เราจะโหลดตัวแปรสภาพแวดล้อมต่อไปนี้ผ่านไฟล์นี้:
SENDGRID_API_KEY=
SENDGRID_FROM=
SENDGRID_TEMPLATE_ID=
MAIL_SUBJECT=
=
ลงชื่อ!SENDGRID_API_KEY
ควรเป็นคีย์ API ที่คุณสร้างในขั้นตอนก่อนหน้านี้SENDGRID_FROM
ควรเป็นที่อยู่อีเมลของคุณ (นี่คือที่อยู่ที่ใช้สำหรับfrom
)SENDGRID_TEMPLATE_ID
ควรเป็นid
สตริงสำหรับเทมเพลตไดนามิกที่คุณสร้างไว้ก่อนหน้านี้MAIL_SUBJECT
จะเป็นหัวเรื่องของอีเมลที่คุณส่ง สำหรับตอนนี้ ให้ตั้งค่านี้เป็น "fCC Tutorial Email"
สุดท้าย สร้าง src
โฟลเดอร์ในไดเรกทอรีโปรเจ็กต์รูทของคุณ และสร้าง send.ts
ไฟล์ในโฟลเดอร์นั้น
วิธีการติดตั้งการพึ่งพาของคุณ
ก่อนอื่นเราต้องติดตั้ง sendgrid
แพ็คเกจ Node.js แพ็คเกจนี้ทำหน้าที่เป็นตัวห่อหุ้มสำหรับ SendGrid API และจะปรับปรุงกระบวนการของเราในการเรียก API เพื่อส่งอีเมล เรียกใช้ npm install @sendgrid/mail
เพื่อติดตั้งแพ็คเกจนี้
จากนั้นเราจำเป็นต้องมีการพึ่งพาการพัฒนาสองสามอย่าง เรียกใช้ npm install --save-dev dotenv @types/node
.
dotenv
จะทำให้เราสามารถโหลดตัวแปรสภาพแวดล้อมจาก.env
ไฟล์ในเครื่อง@types/node
ให้คำจำกัดความประเภทสำหรับ Node.js - TypeScript อาศัยคำจำกัดความเหล่านี้เพื่อทำความเข้าใจโครงสร้างของวิธีการและฟังก์ชันในตัว
วิธีการเขียนลอจิก
ตอนนี้เราจะทำงานใน /src/send.ts
. ของเรา ไฟล์ - นี่คือที่ที่เรากำลังสร้างตรรกะของแอปจำนวนมาก เราจะเริ่มต้นด้วยการนำเข้าค่าที่จำเป็นจากแพ็คเกจของเรา
ก่อนอื่นเราต้องการโหลด dotenv
แพ็คเกจและแยกวิเคราะห์ตัวแปรสภาพแวดล้อมของเรา
import dotenv from "dotenv";
dotenv.config();
dotenv
จำเป็นสำหรับการพัฒนาในพื้นที่เท่านั้น - โฮสต์ออนไลน์ส่วนใหญ่ เช่น Heroku และ Repl.it สามารถจัดการตัวแปรสภาพแวดล้อมได้แบบเนทีฟ
The dotenv.config()
โทรอ่าน .env
. ของเรา ไฟล์และโหลดค่าลงใน process.env
โหนดวัตถุ
ต่อไปเราจะนำเข้าโมดูลที่จำเป็นจากแพ็คเกจ SendGrid:
import sgMail, { MailDataRequired } from "@sendgrid/mail";
sgMail
เป็น wrapper API หลัก และ MailDataRequired
เป็นคำจำกัดความประเภทที่เราต้องการ
สุดท้าย เรานำเข้าคุณสมบัติโหนดในตัวสำหรับจัดการไฟล์ของเรา:
import path from "path";
import { createWriteStream, readFile } from "fs";
path
จะใช้เพื่อค้นหาไฟล์รายชื่ออีเมลของเราที่มีเส้นทางที่เกี่ยวข้องfs
จะใช้ในการอ่านและเขียนไปยังไฟล์เหล่านั้น
ถึงเวลาเริ่มสร้างตรรกะ! แอปพลิเคชันของเราอาศัยค่าที่จำเป็นบางอย่างในการตั้งค่า .env
ดังนั้นเราต้องเริ่มต้นด้วยการตรวจสอบว่าตัวแปรเหล่านั้นถูกตั้งค่าอย่างถูกต้อง หากขาดหายไป เราต้องการให้แอปพลิเคชันของเราออกก่อนเวลาเพื่อหลีกเลี่ยงข้อผิดพลาดเมื่อเราส่งอีเมล
// 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!";
||
ไวยากรณ์บอกรหัสว่าถ้า process.env.MAIL_SUBJECT
ไม่ได้กำหนดหรือผิด ให้ใช้สตริงแทน
process.exit(1)
การเรียกที่คุณเห็นในแต่ละเงื่อนไขการตรวจสอบบอกให้ Node ยุติกระบวนการ (แอปพลิเคชันของเรา) ด้วยรหัสออก 1
. นี่แสดงว่าแอปพลิเคชันของเราขัดข้องเนื่องจากการตรวจสอบอย่างใดอย่างหนึ่งเหล่านี้ล้มเหลว
SendGrid กำหนดให้เราต้องตั้งค่าคีย์ API ด้านล่างลอจิกตัวแปรสภาพแวดล้อม ให้เพิ่มการเรียกใช้ฟังก์ชันเพื่อตั้งค่าคีย์
// Here we set the SendGrid API key
sgMail.setApiKey(apiKey);
ก่อนดำเนินการต่อ ให้เรียกใช้ npm run build
ในเทอร์มินัลของคุณ - สิ่งนี้จะสร้าง prod
โฟลเดอร์ที่มี JavaScript ที่คอมไพล์แล้วของเรา ตอนนี้คุณควรเห็นโครงสร้างไฟล์ต่อไปนี้:
ณ จุดนี้ หากคุณกำลังใช้ git
คุณต้องการที่จะ มั่นใจมาก ว่า prod
โฟลเดอร์จะไม่ถูกผูกมัดกับที่เก็บของคุณ
ภายใน prod
โฟลเดอร์ สร้าง validEmails.csv
ไฟล์. แอพของเราจะใช้ไฟล์นี้เพื่ออ่านรายชื่ออีเมล เริ่มต้นไฟล์ด้วยเนื้อหาต่อไปนี้ (แทนที่ [email protected]
ด้วยที่อยู่อีเมลจริงของคุณ):
email,unsubscribeId
[email protected],1
[email protected],2
.csv
ไฟล์ไม่มีช่องว่างรอบเครื่องหมายจุลภาค
ตอนนี้เราสามารถเขียนโค้ดเพื่อแยกวิเคราะห์ลงในรายชื่ออีเมลได้แล้ว! ใน src/send.ts
. ของคุณ ไฟล์เพิ่มรหัสนี้:
// 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
. ได้ ประกาศแทน ถ้าคุณต้องการ
ตอนนี้ถ้าคุณเรียกใช้ npm run build
และ npm run send
คุณควรเห็นเนื้อหาของ validEmail.csv
. ของเรา ไฟล์ในเทอร์มินัล หากต้องการ คุณสามารถดูความคืบหน้าปัจจุบันของเราได้จนถึงจุดนี้
ยอดเยี่ยม! ตอนนี้ เราต้องแยกสตริงนั้นออกเป็นอาร์เรย์ของอ็อบเจ็กต์ เพื่อให้เราสามารถวนซ้ำและสร้างข้อความอีเมลของเราได้ อัปเดตฟังก์ชันการโทรกลับของเรา:
// 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]
ใช้ destructuring เพื่อกำหนดค่าของ split array ให้กับตัวแปรสองตัวนั้น.split("\n")
แยกสตริงโดยตัวแบ่งบรรทัด หมายเหตุ :หากคุณใช้ Windows คุณอาจต้องเปลี่ยนการตั้งค่าสิ้นสุดบรรทัดสำหรับvalidEmails.csv
ของคุณ จากCRLF
ถึงLF
(Windows แทรกอักขระขึ้นบรรทัดใหม่ที่จะส่งผลต่อการจัดการข้อมูลของเรา).slice(1)
ลบองค์ประกอบแรกของอาร์เรย์นั้น (email,unsubscribeId
. ของเรา บรรทัด)- ของเรา
map
ฟังก์ชั่นจะแปลงแต่ละemail,unsubscribeId
สตริงลงใน{email, unsubscribeId}
วัตถุ
ผลลัพธ์สุดท้ายของฟังก์ชันการแยกวิเคราะห์นี้จะเป็นอาร์เรย์ของวัตถุที่มี email
และ unsubscribeId
คุณสมบัติ - ใช้งานได้ง่ายกว่าสตริงมาก
ถึงเวลาที่จะส่งอีเมลบางส่วน ด้านล่างฟังก์ชันการแยกวิเคราะห์ของคุณ (แต่ยังอยู่ใน readFile
โทรกลับ) เพิ่มโครงสร้างสำหรับวิธีการวนซ้ำของเรา เนื่องจากเราต้องการเข้าถึงแต่ละค่าในอาร์เรย์ เราจะใช้ .forEach
เข้าใกล้
// Here we iterate through the emailList array
emailList.forEach((user) => {});
user
พารามิเตอร์จะเป็น {email, unsubscribeId}
วัตถุ. เราเรียกมันว่า user
เพราะมันแสดงถึงออบเจ็กต์ข้อมูลผู้ใช้ freeCodeCamp ในแอปพลิเคชันแบบเต็ม
ภายในการโทรกลับสำหรับ .forEach
เราสามารถสร้างวัตถุข้อความที่ SendGrid API คาดหวังได้
// 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
}
}
});
ก่อนดำเนินการต่อไป มาดูวัตถุข้อความนี้ให้ละเอียดยิ่งขึ้น MailDataRequired
เรานำเข้าก่อนหน้านี้ใช้เป็นคำจำกัดความของประเภทที่นี่ ดังนั้น TypeScript สามารถแจ้งเตือนเราหากเราพลาดคุณสมบัติที่จำเป็น โชคดีที่เรามีคุณสมบัติที่จำเป็นทั้งหมด แต่มันหมายความว่าอย่างไร?
to:
ที่อยู่อีเมลที่จะส่งข้อความถึง นี่จะเป็นemail
จากแต่ละบรรทัดของvalidEmails.csv
. ของเรา ไฟล์from:
ที่อยู่อีเมลที่จะส่งข้อความจาก มีการตั้งค่าใน.env
. ของเรา ก่อนหน้านี้ (ควรเป็น ของคุณ ที่อยู่อีเมล)subject:
ฟิลด์นี้ไม่จำเป็น แต่ให้ค่าทางเลือกแก่เราในกรณีที่เทมเพลตไดนามิกแยกวิเคราะห์หัวเรื่องของเราไม่ถูกต้องtext:
ค่าข้อความนี้ถูกเขียนทับโดยเทมเพลต อย่างไรก็ตาม มันยังคงเป็นสิ่งสำคัญที่จะใช้ SendGrid สามารถส่งอีเมลเป็นplaintext
หรือhtml
- โดยใช้text
คุณสมบัติแทนhtml
ทรัพย์สิน เรามั่นใจว่าแม่แบบของเราจะถูกส่งเป็นplaintext
. ผู้ให้บริการอีเมล มีแนวโน้มมากขึ้น เพื่อตั้งค่าสถานะข้อความ HTML ว่าเป็นสแปม จึงช่วยเพิ่มอัตราการส่งของเราได้templateId:
นี่คือรหัสสำหรับเทมเพลตแบบไดนามิกที่ SendGrid ควรใช้ในอีเมลdynamicTemplateData:
ค่าเหล่านี้เป็นค่าที่สอดคล้องกับสตริงแฮนด์บาร์ที่เราตั้งค่าไว้ในเทมเพลตไดนามิกก่อนหน้านี้
ยอดเยี่ยม! ขั้นตอนต่อไปของเราคือนำข้อความที่สร้างขึ้นนี้แล้วส่ง ด้านล่างวัตถุข้อความ (แต่ยังอยู่ใน .forEach
โทรกลับ) มาเพิ่มการส่งของเรา:
// Here we send the message we just constructed!
sgMail.send(message);
การดำเนินการนี้จะส่งข้อความไปยังอีเมลแต่ละฉบับใน validEmails.csv
. ของเรา . น่าเสียดายที่รหัสของเราจะทำงานโดยไร้เสียง และเราจะไม่ทราบว่าการส่งแต่ละครั้งสำเร็จหรือไม่ มาเพิ่มการจัดการข้อผิดพลาดกัน
.send()
โทรกลับ Promise ดังนั้นเราจึงสามารถใช้ .then().catch()
เพื่อจัดการกับผลตอบแทน
// 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}`)
});
ตอนนี้ถ้าคุณเรียกใช้ npm run build
และ npm run send
คุณควรเห็นอีเมลที่สวยงามในกล่องจดหมายของคุณ!
ณ จุดนี้ ตอนนี้คุณมีแอปพลิเคชันส่งอีเมลที่ใช้งานได้แล้ว ยินดีด้วย! คุณสามารถดูความคืบหน้าของเราจนถึงจุดนี้ได้หากต้องการ
อ่านต่อไปเพื่อดูวิธีจัดการกับอีเมลตีกลับและตรรกะเพิ่มเติมสำหรับความล้มเหลวในการส่ง ซึ่งเราจะพูดถึงต่อไป
วิธีจัดการอีเมลที่ถูกตีกลับใน SendGrid
คุณอาจสังเกตเห็นว่า [email protected]
มากไม่ใช่ที่อยู่อีเมลจริง SendGrid จะสร้างรายงานตีกลับทุกวันสำหรับกิจกรรมของคุณในวันก่อนหน้า
อีเมลที่ถูกตีกลับทุกฉบับจะสร้างความเสียหายต่อชื่อเสียงของ SendGrid และอาจส่งผลให้ผู้ให้บริการอีเมลทำเครื่องหมายว่าอีเมลของคุณเป็นสแปม เราจึงต้องเพิ่มตรรกะเพื่อป้องกันการส่งไปยังที่อยู่ตีกลับที่ทราบ
เริ่มต้นด้วยการสร้าง bouncedEmails.csv
ไฟล์ใน prod
. ของคุณ โฟลเดอร์ (ควรอยู่ถัดจาก validEmails.csv
. ของคุณ ). เราไม่ต้องการ unsubscribeId
ค่าที่นี่ ดังนั้นเริ่มต้นด้วย:
email
[email protected]
กลับไปที่ send.ts
. ของเรา ไฟล์. ในบรรทัดที่ 38 ด้านล่าง filePath
. ที่มีอยู่ของเรา ประกาศ กำหนดค่าเส้นทางสำหรับ bouncedEmails.csv
ใหม่ ไฟล์.
// 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
ไฟล์).
ยอดเยี่ยม! ตอนนี้เราต้องอ่านไฟล์นั้น ใต้การประกาศเส้นทางไฟล์เหล่านี้ทันที (ก่อน readFile
. ที่มีอยู่ของเรา โทร) เพิ่มตรรกะในการอ่านไฟล์ที่ตีกลับ
// 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
เป็นแบบอะซิงโครนัส - ดังนั้นเราจึงจำเป็นต้องรวมฟังก์ชันการโทรกลับไว้รอบ ๆ ลอจิกการส่งที่มีอยู่ทั้งหมดของเรา . ตรวจสอบให้แน่ใจว่าปิด })
สำหรับการเรียกกลับนี้จะถูกย้ายไปยังส่วนท้ายสุดของไฟล์ของเรา
เราอ่าน bouncedEmails.csv
แยกไฟล์ในบรรทัดใหม่ (จำไว้ว่าคุณจะต้องแน่ใจว่าส่วนท้ายบรรทัดของคุณคือ LF
) และลบ email
ไลน์. สุดท้าย เราดำเนินการกับตรรกะการส่งที่มีอยู่ของเราต่อไป
กลับไปที่ตรรกะการส่งของเรา ภายใน .forEach
. ของเรา ฟังก์ชั่น เพิ่มตรรกะเพื่อข้ามอีเมลที่ถูกบล็อก (เราจะเพิ่มสิ่งนี้ก่อนที่จะสร้างวัตถุข้อความเพื่อหลีกเลี่ยงการสร้างตัวแปรที่ไม่จำเป็น)
// 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
ไฟล์ว่างเปล่า กำลังเรียก includes
จะโยนข้อผิดพลาด ดังนั้นเราจึงตรวจสอบ .length
ให้คุ้มค่าก่อน
โดยใช้ประโยชน์จาก return
early ในยุคต้นๆ คำสั่ง เราจบ .forEach
. นั้น วนซ้ำเมื่อ bounceList
รวมถึงอีเมลนั้นด้วย ซึ่งจะป้องกันไม่ให้เราพยายามส่งไปยังที่อยู่อีเมลที่เคยถูกตีกลับ ตอนนี้ถ้าคุณเรียกใช้ npm run build
และ npm run start
คุณควรเห็นผลลัพธ์นี้ในเทอร์มินัลของคุณ:
ดูความคืบหน้าของเราจนถึงจุดนี้
วิธีการดักจับอีเมลที่ล้มเหลวใน SendGrid
ขณะนี้แอปพลิเคชันของเราจะบันทึกข้อผิดพลาดหากส่งอีเมลไม่สำเร็จ วิธีนี้ใช้ได้กับกรณีการใช้งานขนาดเล็ก แต่เมื่อคุณขยายขนาดแอปพลิเคชัน คุณจะพบว่าการระบุความล้มเหลวเหล่านั้นและพยายามส่งอีกครั้งนั้นยากขึ้นเรื่อยๆ
แต่เราสามารถทำให้แอปพลิเคชันของเราบันทึกอีเมลเหล่านั้นในไฟล์ใหม่แทนได้
สร้าง failedEmails.csv
ไฟล์ใน prod
. ของคุณ โฟลเดอร์ ไฟล์นี้สามารถว่างเปล่าได้ เราจะเขียนโค้ดเพื่อเพิ่มแถวส่วนหัว
กลับไปที่ send.ts
. ของเรา ไฟล์ ไปที่การประกาศเส้นทางของเราในบรรทัดที่ 38 มาเพิ่มอีกสำหรับ failedEmails.csv
ใหม่ของเรา :
// 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");
เส้นทางนี้จะใช้สำหรับ write
. ต่างจากเส้นทางอื่นๆ ของเรา การดำเนินการ. เนื่องจากเราต้องการเขียนอย่างต่อเนื่องในการประมวลผลอีเมล เราจึงต้องสร้างสตรีมเพื่อดำเนินการดังกล่าว ใต้การประกาศเส้นทางเหล่านี้ มาสร้างสตรีมนั้นและเพิ่มแถวส่วนหัวเริ่มต้นของเรา
// Here we create our write stream for failed emails
const failedStream = createWriteStream(failedPath);
// Here we add the header row
failedStream.write("email,unsubscribeId\n")
ถึงเวลาปรับปรุงตรรกะการจัดการข้อผิดพลาดเพื่อรวมสตรีมใหม่นี้ เราต้องเพิ่มอีก write
การดำเนินการกับข้อผิดพลาดของเราในการจัดการใน send
โทร.
// 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`)
});
สิ่งนี้จะเขียน email
และ unsubscribeId
ไปยัง failedEmails.csv
. ใหม่ของเรา ในรูปแบบที่เหมาะสม - ทำให้เราสามารถคัดลอกข้อมูลนั้นลงใน validEmails.csv
เพื่อลองส่งอีกครั้ง
ยินดีด้วย! ตอนนี้คุณได้สร้างเครื่องมือที่ประสบความสำเร็จและทำงานได้อย่างสมบูรณ์เพื่อส่งจดหมายข่าวทางอีเมล คุณสามารถดูรหัสที่เสร็จสมบูรณ์ได้หากต้องการยืนยันงานของคุณ แต่โปรดอ่านต่อเพื่อดูฟีเจอร์เสริม "น่ามี" สองสามอย่าง
คุณลักษณะเสริมสำหรับเครื่องมืออีเมลของคุณ
เนื่องจากเครื่องมือของเราเป็นแบบ CLI (หมายถึงใช้ในอินเทอร์เฟซบรรทัดคำสั่งหรือเทอร์มินัล) จึงไม่มีความคิดเห็นของผู้ใช้มากนัก เราสามารถใช้ประโยชน์จากฟังก์ชันคอนโซลเพิ่มเติมเพื่อให้ข้อมูลเพิ่มเติมเกี่ยวกับความคืบหน้าของสคริปต์ได้
เริ่มต้นด้วยการเพิ่ม "จุดตรวจ" ก่อนการตรวจสอบตัวแปรสภาพแวดล้อมของเรา ให้พิมพ์ข้อความว่าสคริปต์ได้เริ่มต้นแล้วและกำลังตรวจสอบตัวแปรอยู่:
console.info('Script started. Validating environment variables...')
จากนั้น หลังจากตรวจสอบความถูกต้องแล้ว เราก็สามารถพิมพ์ข้อความแสดงความสำเร็จได้
// Here we set the SendGrid API key
sgMail.setApiKey(apiKey);
console.info('Variables confirmed!')
ภายในฟังก์ชันของเราในการอ่านไฟล์ที่ตีกลับ เราสามารถเพิ่มข้อความสำหรับการเริ่มต้น ความล้มเหลว และความสำเร็จได้
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!')
และเช่นเดียวกันสำหรับรายชื่ออีเมลที่ถูกต้องของเรา:
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;
}
ตอนนี้ คงจะดีมากถ้ามีการพิมพ์ข้อความเมื่อการดำเนินการเสร็จสิ้น อย่างไรก็ตาม หากเราเพิ่ม console.info
ต่อจาก .forEach
. ของเรา วนซ้ำ มันจะพิมพ์ ก่อน ส่งอีเมลเสร็จแล้ว!
ทั้งนี้เป็นเพราะ .send
เมธอดสร้างการโทรผ่านเครือข่ายและส่งคืน Promise และ Promise นั้นอาจไม่ได้แก้ไข/ปฏิเสธก่อนที่การทำซ้ำของเราจะเสร็จสิ้น
ดังนั้นเราจึงสามารถสร้างตัวนับเพื่อติดตามจำนวนอีเมลที่เราส่งไปเทียบกับจำนวนอีเมลทั้งหมด ก่อนถึง .forEach
. ของเรา วนซ้ำ เพิ่มตัวแปรเหล่านี้:
// Here we create variables for counting
const emailTotal = emailList.length;
let emailCount = 0;
เราต้องการนับอีเมลที่ถูกตีกลับเป็นการประมวลผล แม้ว่าเราจะข้ามไปก็ตาม
// 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;
}
}
สุดท้ายเราต้องเพิ่มตรรกะเพื่อดูว่าอีเมลที่เราส่งเป็นอีเมลฉบับสุดท้ายหรือไม่ ตรรกะนี้ใช้กับตัวจัดการความสำเร็จและข้อผิดพลาดสำหรับการโทรส่ง:
// 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!`
);
}
});
และด้วยเหตุนี้ แอพของเราจึงสมบูรณ์! หากคุณเรียกใช้ npm run build
และ npm run send
สคริปต์ คุณควรเห็นผลลัพธ์นี้ในเทอร์มินัลของคุณ:
และคุณควรได้รับอีเมลสองสามฉบับที่มีลักษณะคล้ายนี้:
คุณสามารถดูโค้ดสุดท้ายของเราได้ที่นี่ หรือดูเวอร์ชันเพิ่มเติมที่สร้างขึ้นสำหรับ freeCodeCamp