คู่มือ · gmail api

ทีมผลิตภัณฑ์ควรนำ Gmail API ไปใช้อย่างปลอดภัยได้อย่างไร

นำ Gmail API ไปใช้ในฐานะการเข้าถึงแบบมอบสิทธิ์ต่อกล่องจดหมาย Gmail ที่ระบุ ไม่ใช่ข้อมูลรับรองสำหรับส่งอีเมลทั่วไป เลือก OAuth scope ที่เล็กที่สุดที่รองรับฟีเจอร์ ปกป้องสถานะการอนุญาตและ refresh token และให้ทุกกล่องจดหมายอยู่ในขอบเขต tenant สร้างข้อความด้วยไลบรารี Internet message ที่เป็นที่ยอมรับ บันทึก Gmail message ID ที่ได้รับกลับมา และซิงก์การเปลี่ยนแปลงผ่าน Pub/Sub พร้อมบันทึก history ถือว่าการปลอมตัวด้วย service account เป็นการตัดสินใจของผู้ดูแลระบบ Workspace และสุดท้ายให้แยกการที่ API ยอมรับ การส่งถึงเซิร์ฟเวอร์ปลายทาง และการเข้ากล่องจดหมายเป็นผลลัพธ์ที่ต่างกัน

เลือกโมเดลกล่องจดหมายก่อนเขียนโค้ด

Gmail API ทำงานกับกล่องจดหมาย Gmail ของผู้ใช้ เหมาะเมื่อผลิตภัณฑ์ต้องอ่านกล่องจดหมายนั้น จัดระเบียบป้ายกำกับและเธรด สร้างฉบับร่าง ส่งในนามผู้ใช้ที่ได้รับอนุญาต หรือซิงก์การเปลี่ยนแปลงของกล่องจดหมาย สิทธิ์นั้นกว้างกว่าการเรียก email API ของแอปพลิเคชันจากโดเมนผลิตภัณฑ์ที่ยืนยันแล้วอย่างมาก เริ่มด้วยการระบุงานของกล่องจดหมายที่แน่ชัดและผู้ที่ให้สิทธิ์เข้าถึง ผลิตภัณฑ์ที่ผู้ใช้ใช้งานโดยตรงมักใช้ OAuth consent สำหรับแต่ละบัญชี Google ที่เชื่อมต่อ ระบบอัตโนมัติภายในของ Google Workspace อาจใช้ domain-wide delegation ที่ผู้ดูแลระบบอนุมัติแทน หากข้อกำหนดเดียวคือการส่งใบเสร็จ ลิงก์ยืนยัน การแจ้งเตือน หรือข้อความอื่นที่ผลิตภัณฑ์ส่งจากโดเมนที่บริษัทควบคุม ให้หลีกเลี่ยงการเข้าถึงกล่องจดหมายทั้งหมดและประเมิน transactional email API การตัดสินใจด้านสถาปัตยกรรมนี้ลดการเข้าถึงที่ไม่จำเป็นก่อนที่การควบคุมความปลอดภัยหรือหน้าจอขอความยินยอมใด ๆ จะต้องมาชดเชย

ขอสิทธิ์ที่แคบที่สุดเท่าที่ปฏิบัติได้

ตั้งค่า OAuth client ให้ตรงกับประเภทแอปพลิเคชัน ใช้ redirect URI ที่ลงทะเบียนไว้ตรงทุกตัวอักษร และผูกการตอบกลับการอนุญาตกับเซสชันเบราว์เซอร์ที่เริ่มต้นด้วยค่า state ที่คาดเดาไม่ได้ ขอสิทธิ์ตามบริบท คือเมื่อผู้ใช้เปิดฟีเจอร์ที่ต้องใช้ สำหรับการเชื่อมต่อที่ส่งอย่างเดียว `https://www.googleapis.com/auth/gmail.send` แคบกว่า scope ที่อ่านหรือแก้ไขกล่องจดหมาย Google จัด `gmail.send` เป็น sensitive ส่วน scope เช่น `gmail.readonly`, `gmail.compose` และ `gmail.modify` เป็น restricted แอปสาธารณะที่ใช้สิทธิ์ sensitive หรือ restricted อาจต้องผ่านการยืนยัน OAuth และการจัดเก็บหรือส่งข้อมูล restricted-scope ฝั่งเซิร์ฟเวอร์อาจทำให้ต้องผ่านการประเมินความปลอดภัยเพิ่มเติม ขอ offline access เฉพาะเมื่อต้องทำงานเบื้องหลังจริง ๆ เข้ารหัส refresh token ผูกแต่ละโทเค็นกับ tenant ภายในหนึ่งราย และ Google subject หนึ่งราย ห้ามเปิดเผยต่อโค้ดฝั่งเบราว์เซอร์หรือล็อก และมีเส้นทางการยกเลิกการเชื่อมต่อที่ทดสอบแล้ว ซึ่งลบข้อมูลรับรองในเครื่องและหยุดการประมวลผลเบื้องหลัง

ทำความเข้าใจ service account และ domain-wide delegation

service account คือตัวตนของแอปพลิเคชัน ไม่ใช่กล่องจดหมาย Gmail ที่ใช้แทนกันได้ เพียงลำพังมันไม่ได้สิทธิ์เข้าถึงข้อความของพนักงาน สำหรับข้อมูลผู้ใช้ของ Google Workspace ผู้ดูแลระบบระดับสูงต้องอนุญาต client ID ตัวเลขของ service account และรายการ OAuth scope ที่ตรงกันทุกตัวอย่างชัดเจนผ่าน domain-wide delegation จากนั้นแอปพลิเคชันขอข้อมูลรับรองแบบมอบสิทธิ์สำหรับผู้ใช้ที่ระบุชื่อ และการเรียก API แต่ละครั้งทำงานด้วยสิทธิ์ของผู้ใช้นั้นภายใน scope ที่ได้รับอนุญาต ให้ระบุ subject ที่ถูกปลอมตัวอย่างชัดเจนในข้อมูลงานและบันทึกการตรวจสอบ เพื่อไม่ให้ background worker สลับกล่องจดหมายอย่างเงียบ ๆ ได้ ใช้ service account แยกกันสำหรับงานที่ต่างกันอย่างมีนัยสำคัญ หลีกเลี่ยงคีย์ส่วนตัวที่ดาวน์โหลดได้เมื่อรันไทม์ใช้ข้อมูลรับรองที่มีการจัดการได้ และทบทวนสิทธิ์ domain-wide เป็นระยะ บัญชี Gmail ผู้บริโภคไม่มีผู้ดูแลระบบ Workspace ที่จะให้ delegation ระดับองค์กรได้ ดังนั้นสำหรับบัญชีเหล่านั้นให้ใช้ user OAuth consent

ส่งข้อความโดยไม่สูญเสียการควบคุมและการตรวจสอบย้อนหลัง

Gmail รับข้อความอีเมลอินเทอร์เน็ตที่สมบูรณ์ในฟิลด์ `raw` ที่เข้ารหัสด้วย base64url ผ่าน `users.messages.send` ผลิตภัณฑ์ยังสร้างฉบับร่างแล้วส่งภายหลังได้ด้วย ใช้ไลบรารีข้อความที่มีการดูแลเพื่อสร้างโครงสร้าง From, To, Cc, Bcc, Subject, Date, Message-ID, ข้อความล้วน, HTML และไฟล์แนบ แทนการต่อบรรทัดเฮดเดอร์เอง ตรวจสอบผู้รับและเนื้อหาก่อนเข้ารหัส ปฏิเสธ header injection และกำหนดขีดจำกัดขนาดอย่างชัดเจน ทำให้การกระทำของผลิตภัณฑ์เป็น idempotent ก่อนเรียก Gmail คือเก็บ event key ของแอปพลิเคชันที่คงที่ subject ของกล่องจดหมายที่ตั้งใจ และสถานะความพยายามส่ง หลังได้รับการตอบกลับที่สำเร็จ ให้เก็บ message ID และ thread ID ที่ Gmail ส่งกลับมากับอีเวนต์นั้น หากไคลเอนต์ timeout หลังส่งคำขอไปแล้ว ให้กระทบยอดสถานะกล่องจดหมายก่อนลองใหม่ เพราะข้อความอาจถูกยอมรับไปแล้ว การลองใหม่แบบไม่ตรวจสอบอาจทำให้เกิดอีเมลซ้ำแม้การตอบกลับต้นฉบับจะหายไป ใช้การสร้างฉบับร่างพร้อมการตรวจสอบโดยคนเมื่อเนื้อหาหรือผู้รับต้องได้รับการอนุมัติ

ซิงก์การเปลี่ยนแปลงของกล่องจดหมายด้วยบันทึก history

สำหรับการเชื่อมต่อกล่องจดหมายฝั่งเซิร์ฟเวอร์ Gmail watch จะเผยแพร่สัญญาณการเปลี่ยนแปลงผ่าน Google Cloud Pub/Sub การแจ้งเตือนเป็นสัญญาณให้ซิงก์ ไม่ใช่ payload อีเมลที่สมบูรณ์ เก็บ history ID ปัจจุบันและเวลาหมดอายุจากการตอบกลับของ watch ตอบรับการแจ้งเตือนอย่างรวดเร็ว และเรียก `users.history.list` จาก history ID ล่าสุดที่คอมมิตสำเร็จ เพื่อค้นหาการเปลี่ยนแปลงของข้อความและป้ายกำกับ ดึงเฉพาะข้อความที่ฟีเจอร์ต้องใช้ แล้วจึงเลื่อน checkpoint หลังเขียนข้อมูลในเครื่องสำเร็จ การแจ้งเตือนอาจล่าช้าหรือซ้ำ จึงต้องทำให้การประมวลผลข้อความและ history เป็น idempotent Gmail กำหนดให้ต่ออายุ watch ของกล่องจดหมายอย่างน้อยทุกเจ็ดวัน และแนะนำให้ต่อทุกวัน ให้กำหนดเวลาต่ออายุก่อนหมดอายุนานพอ และแจ้งเตือนเมื่อล้มเหลว หาก history ID ที่เก็บไว้อยู่นอกช่วงที่ Gmail มี API จะส่งกลับ HTTP 404 ให้ถือเป็นเส้นทางการกู้คืนที่กำหนดไว้ คือทำการซิงก์เต็มแบบควบคุม สร้าง checkpoint ใหม่ และกลับมาประมวลผลแบบเพิ่มทีละส่วน แทนที่จะลอง history ID ที่ไม่ถูกต้องซ้ำไปเรื่อย ๆ

ใช้เวิร์กโฟลว์การนำไปใช้และการตรวจสอบเป็นขั้นตอน

ขั้นแรก บันทึกว่าฟีเจอร์ส่ง อ่าน แก้ไข หรือ watch อีเมล และแมปแต่ละการดำเนินการกับ OAuth scope ขั้นต่ำ ขั้นที่สอง สร้างโปรเจกต์ Google Cloud หรือ OAuth client แยกกันสำหรับพัฒนาและ production พร้อม redirect URI ที่ตรงกันทุกตัวอักษรและเจ้าของข้อมูลรับรองที่ระบุชื่อ ขั้นที่สาม นำการอนุญาตไปใช้พร้อมการตรวจสอบ state, offline access เฉพาะเมื่อจำเป็น, การจัดเก็บโทเค็นที่เข้ารหัส, การเพิกถอนโทเค็น และการตรวจสอบสิทธิ์ระดับ tenant ขั้นที่สี่ ทดสอบด้วยกล่องจดหมายที่ควบคุม คือเชื่อมต่อ รีเฟรช access token ที่หมดอายุ เพิกถอนความยินยอม เชื่อมต่อใหม่ ส่งหนึ่งครั้ง จำลอง timeout ที่กำกวม และยืนยันการป้องกันการส่งซ้ำ ขั้นที่ห้า หากมีการรับการเปลี่ยนแปลง ให้ตั้งค่าสิทธิ์ Pub/Sub เริ่ม watch ประมวลผล history แบบเพิ่มทีละส่วน บังคับการกู้คืนจาก checkpoint ที่ล้าสมัย และตรวจสอบการต่ออายุ watch ขั้นที่หก เพิ่มคิวงานรายผู้ใช้ exponential backoff ที่มีขอบเขต การจำแนกข้อผิดพลาดแบบมีโครงสร้าง และบันทึกการตรวจสอบที่ไม่รวมเนื้อหาข้อความและโทเค็นเป็นค่าเริ่มต้น ก่อนเปิดตัว ให้ผ่านการยืนยันและการตรวจสอบความปลอดภัยของ Google ที่จำเป็น เผยแพร่การเปิดเผยการใช้ข้อมูลที่ถูกต้อง และซ้อมการหมุนเวียนข้อมูลรับรองและการลบข้อมูลผู้ใช้

วางแผนเรื่องโควตา การลองใหม่ และความล้มเหลวบางส่วน

Gmail วัดการใช้ API เป็นหน่วยโควตา ไม่ใช่เพียงจำนวน request หน้าโควตาของ Google ระบุ 1,200,000 หน่วยต่อนาทีต่อโปรเจ็กต์ และ 6,000 หน่วยต่อนาทีต่อผู้ใช้ต่อโปรเจ็กต์ โดยระบุ `messages.send`, `drafts.send` และ `watch` ที่อย่างละ 100 หน่วย และขีดจำกัดผู้รับ 500 รายต่อข้อความ ขีดจำกัดการส่งของผู้ใช้ Gmail ที่แยกต่างหากยังมีผลกับไคลเอ็นต์ API เว็บ และ SMTP ให้ถือ Cloud console และเอกสารปัจจุบันเป็น input การกำหนดค่าขณะทำงาน แทนการ hard-code ขีดจำกัดที่เผยแพร่ใน business logic ทำงานแบบ serialize หรือเข้าคิวอย่างเป็นธรรมต่อกล่องจดหมาย จำกัด concurrency และลองใหม่เฉพาะการตอบกลับชั่วคราวด้วย exponential backoff ที่มี jitter และ deadline จำกัด อย่าลองใหม่ข้อผิดพลาดการอนุญาต นโยบาย ผู้รับไม่ถูกต้อง หรือข้อความผิดรูปแบบเสมือนเป็นปัญหาความจุ batch แบบ multipart ลด overhead ของการเชื่อมต่อ แต่การเรียกภายในแต่ละครั้งยังใช้โควตาและล้มเหลวแยกกันได้

แยกการยอมรับ การส่งถึง และการเข้ากล่องจดหมายออกจากกัน

การเรียก `messages.send` ที่สำเร็จหมายความว่า Gmail ยอมรับคำขอ API ที่ได้รับอนุญาตและส่งทรัพยากร Message กลับมา ไม่ได้พิสูจน์ว่าเซิร์ฟเวอร์อีเมลของผู้รับทุกรายยอมรับข้อความ และไม่สามารถระบุได้ว่าระบบผู้รับจัดหมวดหมู่ข้อความไว้ที่ใด การส่งถึงเซิร์ฟเวอร์ปลายทางหมายความว่าระบบปลายทางรับผิดชอบ SMTP แล้ว การเข้ากล่องจดหมายเป็นผลของการกรองในภายหลัง เช่น กล่องจดหมายหลัก โปรโมชัน กักกัน หรือสแปม ดังนั้น API กล่องจดหมายของ Gmail จึงไม่ใช่สิ่งทดแทนสตรีมอีเวนต์ของผู้ให้บริการ เมื่อผลิตภัณฑ์ต้องการเทเลเมทรีการส่งถึง อีเมลตีกลับ หรือการร้องเรียนสำหรับอีเมล transactional เก็บ Gmail message ID ไว้เพื่อกระทบยอด แต่ให้อธิบายสถานะที่ผู้ใช้เห็นอย่างแม่นยำว่าส่งแล้วหรือ Gmail ยอมรับแล้ว เว้นแต่มีหลักฐานแยกต่างหากสนับสนุนการส่งถึง การยืนยันตัวตน ผู้รับที่คาดไว้ คุณภาพเนื้อหา พฤติกรรมการส่ง และนโยบายปลายทาง ล้วนส่งผลต่อการจัดการขั้นต่อไป การตอบกลับของ API ไม่สามารถกำหนดหรือรับประกันโฟลเดอร์กล่องจดหมายสุดท้ายของผู้รับได้

รู้ว่าเมื่อใด transactional email API เหมาะกับงานอีกแบบ

ใช้ Gmail API เมื่อผลิตภัณฑ์ต้องเข้าถึงกล่องจดหมาย Gmail ของบุคคลหรือองค์กรโดยได้รับอนุญาต รวมถึงเธรด ป้ายกำกับ ฉบับร่าง หรือการซิงโครไนซ์กล่องจดหมาย Email API สำหรับอีเมล transactional เหมาะกับสถาปัตยกรรมต่างกัน: ข้อความที่แอปพลิเคชันเรียกให้ส่งจากโดเมนที่องค์กรควบคุม โดยไม่มีสิทธิ์ที่มอบหมายให้อ่านกล่องจดหมาย Gmail ของผู้ใช้ ผลิตภัณฑ์ใช้ระบบทั้งสองประเภทได้เมื่อขอบเขตชัดเจน เช่น ใช้ Gmail OAuth เพื่ออ่านกล่องจดหมายที่เชื่อมต่อของเอเจนต์ซัพพอร์ต และใช้ผู้ให้บริการ transactional ที่ยืนยันแยกต่างหากเพื่อส่งใบเสร็จผลิตภัณฑ์ แยกข้อมูลรับรอง ความยินยอม ที่เก็บข้อความ นโยบายลองใหม่ และบันทึกตรวจสอบออกจากกัน เพื่อไม่ให้สิทธิ์กล่องจดหมายรั่วไปสู่การส่งทั้งแอปพลิเคชัน และข้อมูลรับรอง transactional อ่าน Gmail ของผู้ใช้ไม่ได้

คำถามที่พบบ่อย

service account เข้าถึงกล่องจดหมาย Gmail ใดก็ได้หรือไม่

ไม่ service account ไม่ได้รับสิทธิ์เข้าถึงข้อมูลผู้ใช้ Gmail โดยอัตโนมัติ ผู้ดูแลระบบระดับสูงของ Google Workspace ต้องให้ domain-wide delegation แก่ client ID ตัวเลขและ scope ที่ได้รับอนุมัติ หลังจากนั้นแอปพลิเคชันจึงปลอมตัวเป็นผู้ใช้ในองค์กรนั้นอย่างชัดเจนได้ สำหรับบัญชี Gmail ผู้บริโภค ให้ใช้ user OAuth consent แทน

การเชื่อมต่อ Gmail ที่ส่งอย่างเดียวควรขอ OAuth scope ใด

เริ่มด้วยการประเมิน `https://www.googleapis.com/auth/gmail.send` ซึ่งอนุญาตให้ส่งในนามผู้ใช้โดยไม่ให้สิทธิ์อ่านกล่องจดหมายทั่วไป ยืนยันว่าไม่มีข้อกำหนดของผลิตภัณฑ์ที่ต้องใช้ฉบับร่าง การอ่านข้อความ ป้ายกำกับ หรือการแก้ไขจริง ๆ ก่อนขอ scope ที่กว้างกว่า และคำนึงถึงกฎการยืนยัน sensitive scope ของ Google

การส่งผ่าน Gmail API สำเร็จหมายความว่าข้อความส่งถึงแล้วหรือไม่

ไม่ เป็นเพียงการยืนยันว่า Gmail ยอมรับการดำเนินการ API ที่ได้รับอนุญาตและส่งเรคคอร์ดข้อความกลับมา การยอมรับของเซิร์ฟเวอร์ปลายทางและการเข้ากล่องจดหมายเป็นสถานะปลายทางที่แยกกัน อย่าระบุว่าข้อความส่งถึงแล้วหรือสัญญาว่าจะเข้ากล่องจดหมาย เว้นแต่มีสัญญาณที่เชื่อถือได้อื่นสนับสนุนข้อสรุปนั้น

การแจ้งเตือน push ของ Gmail มีข้อความใหม่ทั้งหมดหรือไม่

ไม่ การแจ้งเตือน Pub/Sub ส่งสัญญาณว่าสถานะกล่องจดหมายเปลี่ยนแปลง และมีข้อมูลที่ใช้ซิงก์ต่อ แอปพลิเคชันควรค้นหา history ของ Gmail จาก history ID ที่บันทึกไว้ ดึงข้อมูลข้อความที่ต้องใช้ ประมวลผลแบบ idempotent แล้วจึงเลื่อน checkpoint

ต้องต่ออายุ watch ของกล่องจดหมาย Gmail บ่อยเพียงใด

Google กำหนดให้เรียก `watch` อย่างน้อยทุกเจ็ดวัน และแนะนำให้ต่ออายุทุกวัน ให้เก็บเวลาหมดอายุที่ได้รับกลับมา ต่ออายุก่อนหมดอายุ ติดตามความล้มเหลว และมีงานซิงก์สำรอง เพื่อไม่ให้การต่ออายุที่พลาดสร้างช่องว่างข้อมูลที่ไม่มีขอบเขตอย่างเงียบ ๆ

เมื่อใดทีมควรใช้ transactional email API แทน Gmail API

ใช้ transactional email API เมื่อเป็นอีเมลที่แอปพลิเคชันสั่งส่งจากโดเมนที่องค์กรควบคุม และไม่มีฟีเจอร์ใดต้องเข้าถึงกล่องจดหมาย Gmail ของบุคคล ใช้ Gmail API เมื่อผลิตภัณฑ์ต้องการข้อความ เธรด ป้ายกำกับ ฉบับร่าง การตั้งค่า หรือสิทธิ์ send-as ของกล่องจดหมายที่ได้รับมอบสิทธิ์โดยเฉพาะ

แหล่งอ้างอิง