ส่ง Template Bulk Email ผ่าน SendGrid ด้วย Power Automate

Narisorn Limpaswadpaisarn
EchoO365
Published in
9 min readDec 18, 2021

Content difficulty — Technical

Updated 14/11/2021

วันนี้เราจะมาลองการส่ง Email ด้วย Connector อย่าง Twilio SendGrid เมื่อในการ ส่ง email ให้คนหลายๆคน เช่น Newsletter, Marketing Campaign, แจ้ง Event ต่างๆ ซึ่งเราสามารถใช้ Connector ตัวนี้จาก Power Automate มาช่วยแทน Exchange Online ที่จะมี Recipient limit ต่อวันในการส่ง

ซึ่ง SendGrid สามารถใช้ในมุมข้างต้นได้รวมถึง operation ของ web application ของ user ที่ใช่ app ของเรา เช่น Password Reset, Account confirmation, Purchase confirmation หรือ Support ticket mail ของเรา สามารถ integrate ได้ทั้ง low-code หรือ full code platform เพราะมีทั้ง SMTP Relays, APIs และ Webhook ให้บริการ

SendGrid Connector ใช้ได้ทั้งบน Power Apps, Power Automate และ Azure Logic Apps รายละเอียดดูได้ที่ https://docs.microsoft.com/en-us/connectors/sendgrid/

Send multiple email via Power Automate/ Azure Logic Apps with SendGrid Action

ในตัวอย่างนี้จะสร้างผ่าน Azure Service ที่เป็น Free plan (100 email/day เพื่อการทดลอง) จาก Microsoft Azure Marketplace เนื่องจากมี Azure Subscription และใช้ Account นั้น sign in ใน SendGrid ได้ด้วย ในส่วน SendGrid on Azure นี้จะสร้าง SendGrid Account ได้ 1 SendGrid Account ต่อ 1 Azure Subscription

แต่เราก็ยังสามารถซื้อ Service ตรงได้เองเหมือนกัน ซึ่งแต่ละ plan ก็มี จำนวน email quota ที่ส่งได้ต่อเดือนต่างกัน ตั้งแต่ระดับ หมื่นถึงระดับล้าน และบาง plan ก็มี IP Address dedicated, Single Sign-On และ Email validation ดูเพิ่มเติมได้จาก https://sendgrid.com/pricing/

ซื้อ SendGrid จาก Azure Marketplace อาจจะยังไม่มี feature อย่าง สามารถ overage charge ได้ถ้าอยากส่ง email เกิน quota ที่เรามีใน plan และ SendGrid on Azure นี้จะเป็น Plan ที่เป็น Email API Plans ซึ่งไม่ได้มีในส่วนของ Marketing Campaign Plans ที่จะใช้ใน scenarios ที่เป็นการส่ง email สำหรับ Marketing โดยเฉพาะ

https://azuremarketplace.microsoft.com/en-us/marketplace/apps/sendgrid.tsg-saas-offer

ที่ Azure Portal (https://portal.azure.com/) ก็ create resource แล้ว search ว่า Twilio SendGrid แล้ว Set up เพื่อสร้าง SendGrid Account
สร้าง Service name, Resource Group, เลือก Region และ Plan แล้วก็ Recurring billing กับ Tags
Azure Account นี้คลิก เพื่อ Open และ Sign in ตัว SendGrid Portal ได้เลย รวมถึงเปลี่ยน plan รวมถึง Cancel SendGrid subscription
หลังจากสร้างก็ใช้ Azure Account นี้คลิก เพื่อ Open และ Sign in ตัว SendGrid Portal ได้เลย

Setup พื้นฐาน (API Key + Sender Authentication)

สามารถเข้า SendGrid portal ผ่าน Azure sign in ได้เลย หรือผ่าน (https://app.sendgrid.com/) หลังจากเรามี Account แล้วเราก็มาสร้าง API Key โดยสามารถเลือก ระดับ permission ได้ 3 แบบ ในตัวอย่างเราจะเลือกแบบ Full Access เพื่อความง่าย ถ้าอยากปรับละเอียด เช่น Full access, Read หรือ No access ใน activity ต่างๆ เราอาจจะสร้างอีก key แล้วเลือกเป็น Restrict Access ภายหลังก็ได้ เมื่อสร้างแล้วระบบจะ generate key มาให้ copy เก็บไว้

Settings -> API Keys
เลือก Key permission
เลือก Key permission

ต่อมาเราจะ Set ตัว Email ที่ Sender Authentication ซึ่งจะมีแบบ Single Sender verification จะสามารถส่งในนาม user นั้นๆคนเดียว เราก็จะสร้างเป็น คนๆ ไป หรือจะเป็นแบบ Domain คือ Domain Authentication จากที่ทดลองมาจาก basic setup จะใช้แบบ Domain Authentication เพราะไม่ลง Junk box ของผู้รับ และยังทำ Link Branding เพื่อ Recipients รับ email แล้วคลิกรูป หรือ link ให้แสดงว่าจาก Domain เราแทนที่มาจาก sendgrid.net เพื่อให้ระบบ email เรามีความน่าเชื่อถือ

หลังจากสร้างมาแล้วทั้ง 2 แบบ ถ้ายังไม่มีให้เลือกสร้างได้เลย

แบบ Domain verification ให้เราเลือกผู้ให้บริการ Domain ก่อน เช่น GoDaddy, Google หรือถ้าไม่มีใน list ก็เลือก Others พร้อมใส่ ชื่อ แล้วก็เลือกว่าจะผูก Link Branding หรือไม่ ในตัวอย่างมีใช้ Domain ที่สร้างไว้กับ Hostinger อยู่แล้วเพื่อใช้งาน Microsoft 365 Services

ในกรณีนี้ได้มีการ Host Domain ไว้ที่ Hostinger

จากนั้นระบบก็จะให้เราใส่ Domain และให้ค่า CNAME มาเราก็ copy ค่าไปใส่ใน Domain Provider นั้นๆ ถ้าเราไม่ได้ Host Domain เอง ก็สามารถ Send To A Coworker เป็น email ส่งให้เขาช่วยไปใส่ให้เราได้ พอใส่ครบแล้วก็คลิกเพื่อ verify ถ้าผ่านหมดแสดงว่าใส่ถูกต้องและระบยืนยันว่าเราเป็นเจ้าของ Domain ก็ถือเป้นอันเสร็จสิ้น

ระบบก็ส่งค่า CNAME ให้เราไปใส่ใน DNS Hosting ที่เราใช้บริการ
จากตัวอย่าง Host ใน Hostinger ก็ใส่ CNMAE เข้าไปทั้งหมดทีละอันๆ จากนั้นกลับไปที่ SendGrid แล้ว คลิกเพื่อ verify

ทดลองส่งด้วย SendGrid Connector บน Power Automate

SendGrid ที่มีใน Power Automate ก็มี Action ให้ค่อนข้างหลากหลาย แม้ว่าอาจจะไม่ได้มีทั้งหมดเทียบกับที่ platform สามารถทำได้ ซึ่งในอนาคตก็น่าจะมี Action ที่เข้ามาให้ใช้เพิ่มเติม

Action ต่างๆใน SendGrid

ทดลองกรณีแรก สมมุติต้องการส่งเมลการ นัดสัมภาษณ์งานให้กับ candidate ที่ Progress เป็น Active ทั้งหมดจาก SharePoint List และที่เราจะดึงค่า column มาใส่ใน SendGrid Email คือ Candidate name (Title), Email, Position ตำแหน่งที่สมัคร, วันเวลาสัมภาษณ์ และ คนสำภาษณ์

List ผู้ที่จะได้ Email คือ Progress = Active และแต่ละคนได้วันเวลาและรู้ว่าสัมภาษณ์กับใคร

เราก็ทดลองสร้าง flow ได้ โดยในกรณีนี้เราจะ trigger แบบ manual (Instant Cloud Flow) โดยการไป filter row ใน SharePoint List เราจะให้ Action ที่ชื่อว่า Get Items และ Filter Query ด้วย Progress eq ‘Active’ (single quote ใช้แบบตรงครอบ Active)

ต่อจากนั้นเราจะสร้าง Apply to each เพื่อวนลูปในแต่ละ row ที่ เป็น result จาก Get Items (value) จากนั้นเราก็จะ Filter array ให้เข้ามาแค่ ชื่อ record ในคนๆนั้น เพื่อที่ว่าเวลาส่ง email เขาจะเห็นแค่ข้อมูลสัมภาษณ์ตัวเอง ไม่ดึงมาโชว์ของคนอื่นใน row อื่นด้วย

โดยจับเอา Email ไป is equal to ตัว item()?[‘Email’]) เป็น cursor current position ของ Apply to each นั้น เวลา run

จากนั้นเราก็ Create HTML Table จาก Body ของ Filter array เพื่อตัด column อื่นๆออกโดย จะสร้าง Header และ Value ดังนี้

CandidateName จะใช้ Dynamic Content ชื่อ Title (เพราะได้ rename SharePoint จาก Title เป็น Candidate Name)

Position จะใช้ Dynamic Content ชื่อ Position value

InterviewDate จะได้ค่าเป็น timestamp ในกรณีนี้ tenant ผมไม่ใช้ timezone ไทย เลยจะแปลง timezone ด้วย expression เป็น convertTimeZone(item()?[‘InterviewDate’], ‘Tokyo Standard Time’, ‘Pacific Standard Time’,’g’)

(เป็น single quote แบบตรงหมด)

ใส่ Expression ใช้ร่วมกับ Dynamic Content

Interviewer(s) เนื่องจาก SharePoint column นี้เป็นประเภท People or Group ซึ่งอาจจะมีแค่ 1 คนหรือหลายคน แล้ว return จริงๆถ้าใช้จาก Dynamic content ของ Interviewer(s) ตรงเลยจะเป็น เวลา ทดลอง run flow เราจะเห็นตามภาพ ตามด้านล่าง

ถ้าไม่มีการแปลงด้วย expressions
Result ที่ได้จาด Interviewer(s)

จาก result ที่ได้เราจะใช้ Expression มาแปลงแล้วดึงค่า ผู้สัมภาษณ์ ก็คือ DisplayName มาต่อด้วย , ก็จะเป็น

join(xpath(xml(json(concat(‘{“body”:{“value”:’, item()?[‘Interviewers’] , ‘}}’))), ‘/body/value/DisplayName/text()’), ‘, ‘)

โดย item()?[‘Interviewers’] จะเป็น Dynamic content ของ SharePoint (Get Items) และจะดึงค่า DisplayName มาและคั่นแต่ละคนด้วย , (เป็นฟันหนูตรงหมด)

หลังการใช้ Expression

สุดท้ายเราจะใช้ Compose แปลงตารางจาก HTML Table ให้มีสีหรือ Border โดยใช้ CSS และเอา Output ของ Create HTML Table ใสด้านล่าง

<style>
table {
border: 1px solid #000000;
background-color: #dcefa6;
width: 100%;
text-align: center;
border-collapse: collapse;
}
table td, table th {
border: 1px solid #577b7f;
padding: 3px 2px;
}
table tbody td {
font-size: 13px;
}
table thead {
background: #7d9a3d;
border-bottom: 2px solid #444444;
}
table thead th {
font-size: 15px;
font-weight: bold;
color: #ffffff;
border-left: 2px solid #b2f0a6;
}
table thead th:first-child {
border-left: none;
}
</style>

Apply CSS

สุดท้ายใน Apply to each ก็ใส่ Send Email action ของ SendGrid ได้ โดยเราจะตั้งชื่อและใส่ API Key ที่เราได้จากตอน set up บน SendGrid โดย From จะใส่ email ที่เป็น Distribution list จาก Domain (เช่นกรณีนี้ผมสร้าง HR mail จาก M365 Admin Portal) ที่เราไป verify ใน SendGrid และ Email Body ก็จะใส่ Output ที่ได้จาก Compose ที่เรารวม CSS + HTML Table

ทดลอง run ในกรณีนี้มี Active 3 คน ซึ่งแต่ละคนจะได้รับ email นัดสัมภาษณ์ตามตาราง HTML ที่มี CSS Style ตารางเขียว
ในหน้า SendGrid Dashboard ก็สามารถดู Statistic ในการส่งเมลทั้งหมดได้
สามารถดู actvity ได้ว่าส่งไปหาใครบ้าง

การส่ง Email ผ่าน Dynamic Template ของ SendGrid

กรณีสอง เราสามารถสร้าง Template mail ที่มี Graphics ได้อยู่แล้วผ่าน portal ของ SendGrid ได้เลย โดยไม่ต้อง CSS ใน Power Automate จาก Design Library https://mc.sendgrid.com/design-library/ ซึ่งมี ทั้งเราสร้างเอง + upload รูป หรือ เริ่มจาก Template ที่มีให้ สามารถ edit ให้เป็นตามที่เราต้องการเพิ่มเติม จาก Design Editor (แบบ Graphic canvas) หรือ ใส่เป็น Coding ผ่าน Code Editor

ให้สร้างเอง หรือเลือกจาก Template เช่น Newsletter, Event, Black Friday ต่างๆ

โดยตอนนี้ทดลองสร้างเองผ่าน Design Editor สามารถ Drag and Drop ตัว Content ต่างๆได้ เช่น รูปภาพ, Text, Social media link รวมถึงการ Test ส่ง email ดูได้

Design Editor
Design Editor

นอกจากนี้เราสามารถ สร้าง ตัวแปรที่เป็น Dynamic Content ได้ผ่าน {{variable}} เพื่อที่เราจะผ่านค่า parameter ใน template นี้ได้จาก Custom application หรือ API Service ที่เราจะ Develop ไปหา

สมมุติเราจะทำระบบส่ง บิลไปให้ user ต่างๆผ่าน Email โดยเรากำหนด Dynamic Content เช่น ชื่อลูกค้า ({{CustomerName}}), Account ID ({{AccId}}), ค่าใช้จ่าย ({{TotalCost}}) และ link สำหรับลูกค้าที่จะคลิกเพื่อ download บิล แบบ .pdf ({{Weblink}})

ใส่ Dynamic Content
ใส่ Dynamic Content
ทดลอง Preview โดยการเขียน Test Data ในรูป JSON

เมื่อ Design เรียบร้อยเราจะไปสร้าง Dynamic Template ซึ่งสามารถเอา Template ที่เรา Design เก็บไว้เป็น Version ต่างๆได้ และระบบจะ Generate ตัว Template ID ที่เราจะต้องเก็บไว้ใช้ในการ call จาก Power Automate หรือ APIs App ของเรา

สร้าง Dynamic Template และ copy ค่า Template ID
Import ที่เรา Design และ set ให้เป็น Active เพื่อใช้ Mail Template version นี้

จากนั้นเราทำการสร้าง Flow เพื่อ Call แต่เพื่อความง่ายในการทดสอบขอ สร้างแบบ Instance Cloud Flow แต่ใส่ list รายชื่อคนที่เราจะส่งเป็นในรูปแบบตัวแปร โดยกำหนดตัวแปรชื่อ varMail เป็นประเภท Array จาก Initialize Variable ในตัวอย่างนี้ทดสอบแค่ 2 คน โดยเพิ่ม field ที่เป็น “email” นอกนั้นสร้างตัว field ให้ชื่อเหมือนกับใน Dynamic Template ของ SendGrid

[
{ “email”: “user1@domain1.com”, “CustomerName”: “User 1”,
“AccId”: “RR3443”, “TotalCost”: “$500”,
“Weblink”: “https://link.medium.com/sB1W30IL7kb" },
{ “email”: “user2@domain2.com”,”CustomerName”: “Company Y Thailand”,
“AccId”: “AI3248”, “TotalCost”: “$1200”,
“Weblink”: “https://link.medium.com/stSRn9BL7kb"
}
]

ฟันหนูแบบตรงทั้งหมด

ใส่ชื่อ Dynamic Content ให้เหมือน Dynamic Template ของ SendGrid เพื่อความง่าย

จากนั้นเราใส่ Apply to Each โดยใช้ varMail ให้ลูปวนที่ละชื่อ email ที่จะส่ง แล้วก็สร้างตัวแปรชื่อ Compose เพื่อใส่ JSON ลงไป

สุดท้ายเนื่องจากการ ส่ง email แบบ Dynamic Template ยังไม่มี Action นี้ให้ใช้ใน SendGrid Connector ของ Power Automate (ตอนนี้มีแต่ส่ง email ธรรมดาแบบในอันที่แล้ว ซึ่งไม่มีสั่งไปเอาที่ template) จึงจำเป็นต้องใช้แบบ HTTP แทน โดยใช้ Action อย่าง HTTP ดั่งรูปด้านล่าง

จาก Initialize variable ก็มาที่ Compose + HTTP ที่อยู่ใน Apply to each loop

เราจะมาใส่ค่าในแต่ละ Action กันโดย Compose จะใส่เป็น (ดูรูปประกอบ)

{
“from”: {
“email”: “xxx@yyy.com
},
“personalizations”: [
{
“to”: [
{
“email”:”aa@bbb.com
}
],
“dynamic_template_data”: {
“CustomerName”: “ECHOO365”,
“AccId”: “XXXX”,
“TotalCost”: “$6999”,
“Weblink”: “www.xxx.com
}
}
],
“template_id”: “d-2fxxxxxxxxxxxxxxxxxxxxxxxx”
}

Compose + Expression

จากรูปบน Compose คือส่วนที่เป็น JSON body ของ HTTP Action อันต่อไปนั้นเองซึ่ง JSON นี้ จะเป็นโครงสร้างที่ใช้บอกว่าจะยิงไปที่ Dynamic Template ไหนใน SendGrid (ก็ตาม ID ที่เราได้มาตอนสร้าง version) โดยมี Dynamic Content อะไรบ้าง ส่งโดยใครไปหาใคร

รายละเอียดของ JSON Body และการทำ API call อ้างอิงจาก https://docs.sendgrid.com/ui/sending-email/how-to-send-an-email-with-dynamic-transactional-templates

โดยจากรูปก็คือส่งโดย app@mwlab.xyz เป็น ผู้ส่งผู้รับเราก็ต้องมาใส่ Expression ที่บอกว่าจาก Array item นั้นๆคือ ค่าในช่อง “email” นั่นคือ item()?[‘email’]

“dynamic_template_data” ก็จะเป็น list ที่เราจะส่งค่า Dynamic Content ทั้งหมดตามที่เราตั้งไว้ใน Dynamic Template ก็ตั้งตามชื่อ {{variable}} ที่เราตั้งมา ส่วนค value นั้นเราก็เขียน Expression ตาม field ที่เรากำหนดใน Initialize variable ก็จะอยู่ในรูปแบบ item()?[‘variable’] ซึ่งเราก็ใช้ชื่อเหมือนกันทั้งสองฝั่ง

“template_id” คือ Dynamic Template ID จาก SendGrid

ทุกอันเป็นฟันหนูตรง จากนั้นเรามาทำ HTTP Action กันต่อ

โดยจะใช้ POST method ยิงไปที่ https://api.sendgrid.com/v3/mail/send

Header จะใช้ Content-Type เป็น application/json และ Authorization เป็น Bearer เว้นวรรคตามด้วย SendGrid API Key ที่เราได้มาตอน Basic Setup

จากนั้น Body ก็นำ Output ที่ได้จาก Compose มาใส่

HTTP Action จะเป็น Premium Connector ซึ่งจะมี License เพิ่มเติมอย่าง Plan ชื่อ Power Automate per user ($15/month ซึ่งเอาไปสร้างใน flow อิ่นๆได้) โดย user ขององค์กรก็สามารถ Trial ได้ https://powerautomate.microsoft.com/en-us/#home-signup

ทดลอง run flow ก็จะเห็น email template ยิงเข้ามาตาม email list ในตัวแปร Array จริงๆ

ทดลองส่ง

การปรับ Pagination และ Concurrency Control

ใน SharePoint Online เวลา Get items สามารถดึงมาได้สูงสุด ประมาณ 5,000 items (rows) โดยเป็น limit ของ Power Automate ที่มากับ Office 365 License ส่วน Plan อื่นๆ เช่น Power Automate per user, Power Automate per flow จะได้มากกว่านั้น ซึ่งไปเพิ่มให้มากกว่า 5,000 ได้ที่ตัว Pagination (สูงสุดคือ 100,000 items ณ ตอนนี้)

Pagination

ในส่วน Apply to each จะเป็นการ Process ทีละ row ตาม output order ที่เราส่งไป เราสามารถเร่งทำให้ process แบบขนานกันได้โดยปรับ Concurrency เพื่อให้ flow ทำงานเร็วขึ้น เหมาะสำหรับกรณีที่เราไม่ได้ต้องการเรียงเป็น order หรือ แต่ละ row ต้องรอค่าของอันก่อนหน้า

ปรับ concurrency ให้ได้สุดถึง 50

Governance

เนื่องด้วยเป็น Service ที่ส่งเมลทีละหลายๆ mail ก็ค่อนข้างที่จะต้องระวังเป็นพิเศษในการอนุญาตให้ใช้ Connector (SendGrid, HTTP) กับพนักงานในองค์กร เพื่อไม่ให้ใครก็ได้ในองค์กรหยิบจับไปทำมากเกินไปจนคุมการใช้งานไม่ได้ ซึ่งประเด็นในการทำ governance ในหัวข้อนี้

  1. เรื่อง SendGrid API key ที่ต้องดูแลให้ใช้โดยเฉพาะบาง user รวมไปถึง การ rotate key หรือ Set ในส่วนของ Key Permission (Restricted Access)
  2. การสร้าง Power Platform Environment ใหม่ที่สงวนไว้ให้เฉพาะของการทำระบบ App หรือ Flow ที่ใช้ SendGrid Connector ตัวนี้ แยกกับ Default Environment (ที่เป็นพื้นที่ๆ ให้ user ทุกคนใน Tenant สร้าง App หรือ Flow ได้) แล้วก็อาจจะทำการ Set ตัว DLP Rules (Environment owner หรือ Power Platform admin เข้าไปที่ https://admin.powerplatform.microsoft.com/dlp) นี้แล้ว block ตัว SendGrid connector ใน Default Environment
  3. การขออนุญาตในการใช้ SendGrid หรือ connector พวกนี้ทางองค์กรควรจะทำในส่วนของระบบ request ภายใน
DLP ใน Power Platform
จัดกลุ่มของ connector ให้ทำงานร่วมกัน หรือ Block ไปเลย

ซึ่งกลุ่มของ Blocked ก็คือไม่สามารถใช้ connector นั้นๆในการใช้งานร่วมกับการสร้าง Power App หรือ Power Automate ได้

ส่วน Business และ Non-business เป็นการแบ่งกลุ่มเฉยโดยถ้า connector อยู่กลุ่มเดียวกัน ผู้พัฒนาสามารถใช้งาน connector นั้นร่วมกันใน flow นั้นๆ หรือ App นั้นๆได้ แต่ไม่สามารถใช้งานข้ามกลุ่มได้ connector ที่อยู่กลุ่ม Business สามารถใช้ต่อเนื่องกับ Business และ Non-business ใช้ได้เฉพาะกับ Non-business

ใช้กับ Service อื่น

ตัว SendGrid และ HTTP connector นี้ยังสามารถใช้กับ Azure Logic Apps หรือ Power Apps ได้เช่นกัน โดยการใช้ก็ต้องสร้าง connection โดยใช้ API Key

Azure Logic Apps ที่ใช้งานเหมือน Power Automate ในจุดนี้
ใช้ผ่าน Power Apps ซื่อมี function ที่ต้อง Input ค่าคล้ายๆ Power Automate

สามารถดูเนื้อหาและ demo ผ่าน YouTube ได้ครับ

--

--

Narisorn Limpaswadpaisarn
EchoO365

Office 365 and Modern Workplaces: Please follow my publication https://medium.com/echoo365 for Microsoft 365 & Power Platform Blog (In Thai)