ต้องเตรียมอะไรบ้างก่อนเริ่ม?
การทดสอบ OTP อีเมลด้วย Playwright มีงานสองส่วน: ควบคุมหน้าเว็บ และอ่านอีเมลที่แอปส่งออกมา ให้แยกสองส่วนนี้ไว้คนละฟังก์ชัน เพื่อดูได้ว่าชุดทดสอบล้มเหลวที่หน้าเว็บ การรับอีเมล หรือการยืนยันรหัส
Mailera เชื่อมกล่องจดหมายเดิมเข้ากับแอป ผ่าน REST API จึงไม่ต้องเปลี่ยนที่อยู่อีเมลของบัญชีทดสอบ หากต้องการดูพื้นฐานก่อนเขียนชุดทดสอบ อ่านวิธีอ่าน OTP จากกล่องจดหมายของคุณ
| สิ่งที่ต้องมี | การเตรียมที่แนะนำ |
|---|---|
| แอปและบัญชีทดสอบ | ใช้เฉพาะระบบที่คุณได้รับอนุญาตให้ทดสอบ |
| กล่องจดหมายของคุณ | แยกจากกล่องจดหมายส่วนตัวที่มีข้อมูลจริง |
| Playwright | ใช้โครงการทดสอบที่เปิดหน้าล็อกอินของแอปได้แล้ว |
| คีย์ API | จำกัดขอบเขตเฉพาะกลุ่มกล่องจดหมายทดสอบ และให้สิทธิ์ read |
| ข้อมูลสำหรับจับคู่รอบ | ถ้าแอปทดสอบทำได้ ให้ใส่ตัวระบุเฉพาะรอบในหัวข้ออีเมล; ถ้าทำไม่ได้ ให้รันทีละรอบต่อกล่องจดหมายแทน |
| ระบบเก็บความลับ | เก็บคีย์ในตัวแปรสภาพแวดล้อมหรือระบบจัดการความลับของ CI |
สำหรับ Outlook และ Microsoft 365 ใช้การเชื่อม Microsoft ผ่าน OAuth ไม่ใช่รหัสผ่านสำหรับแอป ส่วนการเชื่อม Gmail ของ Mailera ใช้รหัสผ่านสำหรับแอป (app password) ซึ่ง Google กำหนดให้บัญชีเปิดการยืนยันสองขั้นตอน ตามข้อกำหนดรหัสผ่านสำหรับแอปของ Google
หากต้องแยกว่ารหัสผ่านประเภทนี้ต่างจากรหัสผ่านบัญชีอย่างไร อ่านรหัสผ่านสำหรับแอปของกล่องจดหมาย ก่อนตั้งค่าการเชื่อมต่อ
ใน Mailera เปิด การตั้งค่า ไปที่แท็บ API key แล้วเลือก สร้าง API key กำหนด ขอบเขตกล่องจดหมาย ให้เป็นกลุ่มทดสอบ และเลือกสิทธิ์ read คีย์ใหม่จะแสดงเพียงครั้งเดียว จึงควรบันทึกลงระบบจัดการความลับทันที ไม่ใส่ไว้ในไฟล์ที่ส่งเข้า Git

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

1. เลือกกล่องจดหมายให้ชัดเจน
ก่อนเรียกคำสั่งแรก ให้โหลดคีย์จากระบบจัดการความลับลงตัวแปรสภาพแวดล้อม MAILERA_API_KEY ของ shell หรือขั้นตอน CI ที่จะรันคำสั่ง โดยไม่พิมพ์ค่าคีย์ลง log
เรียก GET /mailboxes แล้วตรวจ email, group_id และ id ของรายการที่ต้องการ อย่าเลือก data[0] โดยอัตโนมัติ เพราะลำดับรายการไม่ใช่ตัวระบุบัญชีทดสอบ
curl --fail-with-body \
'https://mailera.app/api/public/v1/mailboxes' \
-H "Authorization: Bearer $MAILERA_API_KEY"หากยังไม่พบกล่องจดหมาย ให้ตรวจหน้าถัดไปด้วย limit และ offset แล้วบันทึก id ที่เลือกลง $MAILBOX_ID ส่วนคีย์เก็บใน $MAILERA_API_KEY ผลลัพธ์คำสั่งนี้มีข้อมูลกล่องจดหมาย จึงไม่ควรส่งออกไปยังบันทึก CI ที่เปิดอ่านได้ทั่วไป
ก่อนเรียกคำสั่งถัดไป ให้ตั้งค่าตัวแปรต่อไปนี้ให้ครบในสภาพแวดล้อมเดียวกัน ใช้ค่าจริงของระบบและกล่องจดหมายทดสอบที่คุณได้รับอนุญาตให้ใช้
| ตัวแปรสภาพแวดล้อม | ค่าที่ต้องกำหนด |
|---|---|
MAILERA_API_KEY | คีย์ที่มีสิทธิ์ read และเข้าถึงกลุ่มกล่องจดหมายทดสอบได้ |
MAILBOX_ID | ค่า id ของกล่องจดหมายที่เลือกจากผลลัพธ์ด้านบน |
TEST_OTP_FROM | ที่อยู่ผู้ส่งที่แอปใช้ส่ง OTP |
TEST_OTP_SUBJECT | หัวข้อเต็มที่มีตัวระบุเฉพาะรอบ และตรงกับหัวข้อที่แอปจะส่ง |
หากรันใน shell ให้ส่งออกตัวแปรเหล่านี้ด้วย export หากรันใน CI ให้ส่งตัวแปรเข้าขั้นตอนที่เรียก API ด้วย ไม่ใช่ตั้งไว้เฉพาะขั้นตอนเตรียมงาน สำหรับ GitHub Actions ดูวิธีส่ง secrets ให้ขั้นตอนรันผ่านตัวแปรสภาพแวดล้อม

2. เลือกวิธีอ่านรหัสให้เหมาะกับการตรวจรอบ
GET /mailboxes/{id}/otp ใช้อ่าน OTP ล่าสุด โดยมีตัวกรอง from, subject และ since_minutes และต้องใช้สิทธิ์ read
curl --fail-with-body --get \
"https://mailera.app/api/public/v1/mailboxes/$MAILBOX_ID/otp" \
-H "Authorization: Bearer $MAILERA_API_KEY" \
--data-urlencode "from=$TEST_OTP_FROM" \
--data-urlencode "subject=$TEST_OTP_SUBJECT" \
--data-urlencode 'since_minutes=5'ตัวอย่างนี้ส่ง since_minutes=5 พร้อม from และ subject ระวังผลลัพธ์คำสั่งนี้มีรหัสที่ต้องปกปิด
หากต้องการตรวจข้อมูลของข้อความก่อนใช้รหัส ให้ใช้ GET /messages/search พร้อม mailbox, from, q และ extract=otp แล้วอ่าน otp.code จากผลลัพธ์ พร้อมตรวจ to, subject และ received_at ของข้อความเดียวกันประกอบ ดูรายการปลายทาง API เพิ่มเติมในเอกสาร API ของ Mailera
3. แยกตัวช่วยอ่านอีเมลออกจากหน้าเว็บ
ให้ตัวช่วยอ่านอีเมลรับข้อมูลของรอบทดสอบจากส่วนควบคุมหน้าเว็บ ได้แก่ กล่องจดหมาย ผู้รับ ผู้ส่ง หัวข้อเฉพาะรอบ และเวลาเริ่มขอรหัส กำหนดเส้นตายรวมให้ตัวช่วยนี้ด้วย เพื่อไม่ให้ชุดทดสอบรออีเมลโดยไม่สิ้นสุด
ภายในตัวช่วย ให้เรียงการทำงานดังนี้:
- ค้นหาข้อความด้วยกล่องจดหมายและผู้ส่งที่กำหนด พร้อมใช้หัวข้อเฉพาะรอบเป็นคำค้น
- ตรวจ
mailbox_id,from.address, ผู้รับในto,subjectและreceived_atของผลลัพธ์ก่อนอ่านotp.codeอย่าถือว่าการค้นเจอคำในหัวข้อเพียงอย่างเดียวเพียงพอ - หากมี
next_cursorให้ตรวจหน้าถัดไปหรือหยุดเพื่อปรับตัวกรอง อย่าเลือกข้อความแรกโดยละเลยผลลัพธ์ที่เหลือ - หากพบข้อความตรงเงื่อนไขมากกว่าหนึ่งฉบับ ให้หยุดด้วยข้อผิดพลาดที่ระบุว่าเลือกข้อความไม่ได้ แทนการเดารหัส
- หากยังไม่พบ ให้พักก่อนตรวจซ้ำ และหยุดเมื่อครบเส้นตาย
การตรวจ received_at เป็นเงื่อนไขเสริม ไม่ใช่หลักฐานเดียวว่าข้อความเป็นของรอบนี้ จุดที่ใช้จับคู่รอบคือหัวข้อเฉพาะรอบซึ่งแอปของคุณสร้างหรือรับค่าจากการตั้งค่าทดสอบ
วงรอควรทำซ้ำเมื่อยังไม่พบข้อความที่ตรงเงื่อนไข แต่ไม่ควรกลืนข้อผิดพลาด HTTP แล้วลองใหม่ทุกชนิด กรณีคีย์ผิดหรือไม่มีสิทธิ์ควรหยุดเพื่อแก้การตั้งค่า ไม่ใช่ใช้เวลารอทั้งหมดกับคำขอเดิม
4. ขอรหัส กรอกกลับ และตรวจสถานะหลังล็อกอิน
ในส่วนควบคุมหน้าเว็บของ Playwright ให้ใช้ชื่อช่องและปุ่มที่ตรงกับแอปทดสอบของคุณ แล้วเรียงขั้นตอนดังนี้:
- เปิดหน้าล็อกอินและกรอกที่อยู่อีเมลของบัญชีทดสอบที่ตรงกับกล่องจดหมายที่เลือกไว้
- บันทึกเวลาเริ่มต้นก่อนกดขอรหัส แล้วส่งเวลาและข้อมูลประจำรอบให้ตัวช่วยอ่านอีเมล
- รอรหัสจากข้อความที่ผ่านเงื่อนไข หากตัวช่วยหมดเวลาหรือเลือกข้อความไม่ได้ ให้จบรอบด้วยข้อผิดพลาด ไม่กดขอรหัสใหม่เองในวงรอ
- กรอกรหัสและกดยืนยัน จากนั้นตรวจองค์ประกอบที่แอปแสดงเฉพาะเมื่อเข้าสู่ระบบแล้ว
หากหน้าเว็บแสดงบัญชีที่เข้าใช้ ให้ตรวจด้วยว่าเป็นบัญชีทดสอบที่ต้องการ อย่าจบการทดสอบทันทีหลังกรอกรหัส
เก็บคีย์ API ไว้ในกระบวนการรันชุดทดสอบ ไม่ส่งเข้า JavaScript ของหน้าเว็บ โครงสร้างการเชื่อมต่อแบบนี้อธิบายเพิ่มเติมไว้ในหน้าสำหรับนักพัฒนา
จะรอรหัสโดยไม่หยิบ OTP เก่าหรือรหัสของงานอื่นได้อย่างไร?
ปลายทาง API สำหรับอ่าน OTP รองรับ from, subject และ since_minutes แต่ชุดทดสอบควรตรวจข้อความกับตัวระบุเฉพาะรอบก่อนใช้รหัส อย่าเลือก OTP เพียงเพราะเป็นรหัสล่าสุด
ให้แยกการตรวจเป็นสองเรื่องหลัก:
- กล่องและผู้รับถูกต้อง: ระบุ
$MAILBOX_IDและตรวจผู้รับของข้อความ อย่าอาศัยเพียงที่อยู่ผู้ส่ง - ข้อความตรงรอบ: ใช้ตัวระบุเฉพาะรอบในหัวข้อหรือเนื้อหาเมื่อแอปรองรับ พร้อมตรวจเวลาเป็นเงื่อนไขเสริม
- รหัสยังใช้ได้: ให้แอปเป็นผู้ตัดสิน แล้วตรวจผลหลังยืนยันรหัส การเลือกอีเมลถูกฉบับไม่ได้แปลว่าแอปจะยอมรับรหัสนั้น
หากแอปใส่ตัวระบุไว้ในเนื้อหา ใช้ GET /mailboxes/{id}/messages เพื่อค้นหารายการ แล้วอ่าน GET /mailboxes/{id}/messages/{msgId} ตรวจ body.text หรือ body.html ก่อนเลือก OTP รายการข้อความมีตัวกรอง from และ since รวมถึง cursor สำหรับหน้าถัดไป
สำหรับแอปที่ไม่มีตัวระบุเฉพาะรอบ ให้รันทีละรอบต่อกล่องจดหมาย และอย่ามีงานอื่นขอ OTP ให้บัญชีเดียวกันระหว่างนั้น หากแยกไม่ได้ว่าข้อความเป็นของรอบใด ให้หยุดด้วยผลที่ระบุว่าเลือกข้อความไม่ได้ แทนการเดารหัสล่าสุด
เมื่อรันหลาย worker ให้แยกบัญชีและกล่องจดหมายของแต่ละ worker อย่าให้ทุกงานใช้ $MAILBOX_ID เดียวกันแล้วแข่งกันอ่านรหัส
ข้อผิดพลาดที่พบบ่อยและวิธีตรวจสอบ
เริ่มจากดูว่าอีเมลมาถึงหรือไม่ ก่อนเพิ่มเวลารอ หากข้อความยังไม่ถูกซิงก์ การเปลี่ยนตัวเลือกช่องกรอก OTP ใน Playwright จะไม่ช่วยแก้ปัญหา
| อาการ | จุดที่ควรสงสัย | ขั้นตอนตรวจสอบ |
|---|---|---|
| ไม่พบ OTP | ผู้ส่ง หัวข้อ หรือกล่องจดหมายไม่ตรง | ตรวจค่าตัวแปรและข้อความจริง โดยปิดบังรหัส |
| พบรหัสแต่แอปปฏิเสธ | เลือกข้อความผิดรอบ หรือรหัสไม่ผ่านกติกาของแอป | ตรวจตัวระบุรอบและประวัติการขอรหัสใหม่ |
| รอจนหมดเวลา | การส่งอีเมล การเชื่อมต่อ หรือการซิงก์ | ตรวจ /status และเวลาซิงก์ล่าสุด ก่อนขยายเส้นตาย |
| อ่านผิดกล่อง | เลือกรายการแรกหรือแชร์ค่าระหว่าง worker | เทียบ id, email, group_id กับบัญชีทดสอบ |
| คีย์ใช้เรียกไม่ได้ | สิทธิ์หรือขอบเขตกล่องจดหมายไม่ตรง | ตรวจ read กลุ่มที่คีย์เข้าถึงได้ และการเพิกถอนคีย์ |
| ค้นพบหลายข้อความ | ใช้หัวข้อซ้ำหรือมีการขอรหัสซ้ำ | หยุดรอบนั้น แล้วเตรียมตัวระบุใหม่ |
GET /mailboxes/{id}/status ตรวจการลงชื่อเข้าใช้ Microsoft โดยตรง ส่วนผู้ให้บริการอื่นใช้สถานะจากการซิงก์ล่าสุด จึงควรดู last_sync_at ประกอบ ไม่ตีความทุกสถานะว่าเป็นการลงชื่อเข้าใช้ใหม่ในขณะนั้น
หากต้องสั่งซิงก์เอง POST /mailboxes/{id}/sync ต้องมีสิทธิ์ sync เพิ่มจาก read และใช้ปลุกกล่องจดหมายที่อยู่ในโหมดพักได้ ไม่จำเป็นต้องเพิ่มสิทธิ์นี้ให้คีย์อ่าน OTP ทุกคีย์
กรณีไม่พบข้อความในกล่องจดหมายเข้า ตรวจ GET /mailboxes/{id}/placement โดยใช้ from, subject และ since_minutes หรือเปิดโฟลเดอร์อีเมลขยะของ Outlook และสแปมของ Gmail หากพบอีเมลในโฟลเดอร์เหล่านี้ ใช้ปุ่ม ไม่ใช่อีเมลขยะ ในหน้าอ่านอีเมลของ Mailera เพื่อย้ายออกมา แต่แยกขั้นตอนนี้ออกจากชุดทดสอบล็อกอินอัตโนมัติ ไม่ควรย้ายจดหมายอัตโนมัติในชุดทดสอบนี้
สำหรับ Gmail ที่เคยเชื่อมได้แล้วหยุดทำงานหลังเปลี่ยนรหัสผ่านบัญชี ให้ตรวจรหัสผ่านสำหรับแอปด้วย เพราะ Google เพิกถอนรหัสผ่านสำหรับแอปเมื่อเปลี่ยนรหัสผ่านบัญชี
แยก “อ่าน API ซ้ำ” ออกจาก “กดส่ง OTP ใหม่” วงรอควรอ่านอีเมลอย่างเดียว หากต้องทดสอบการส่งใหม่ ให้กำหนดพฤติกรรมของรหัสก่อนหน้าตามกติกาแอป แล้วเขียนเป็นกรณีทดสอบแยก
จะเก็บคีย์และ OTP ให้ปลอดภัยระหว่างทดสอบได้อย่างไร?
ใช้เฉพาะกล่องจดหมายของคุณและบัญชีที่ได้รับอนุญาตให้ทดสอบ จำกัดสิทธิ์คีย์ไว้ที่กลุ่มทดสอบ และอย่าเพิ่ม send หรือ move ให้ตัวช่วยที่มีหน้าที่อ่านอย่างเดียว ดูข้อมูลประกอบในหน้าความปลอดภัยของ Mailera
อย่าบันทึกส่วนหัว Authorization ผลตอบกลับที่มี OTP หรือเนื้อหาอีเมลทั้งหมดลง log ข้อความผิดพลาดควรบอกขั้นตอนที่ล้มเหลวโดยไม่แนบรหัส เช่น “ไม่พบข้อความที่ตรงรอบภายในเส้นตาย”
ก่อนเปิดการจัดเก็บ trace ภาพหน้าจอ วิดีโอ และรายงานของ CI สำหรับชุดทดสอบนี้ ให้ตรวจก่อนว่าไฟล์เหล่านี้จะมีค่าที่กรอกหรือข้อมูลคำขอติดไปด้วยหรือไม่ ควรปิดการบันทึกภาพและ trace หากไม่จำเป็น หากต้องเปิดเพื่อแก้ปัญหา ให้จำกัดผู้เข้าถึง ระยะเวลาเก็บ และปิดบังข้อมูลก่อนแชร์
ถือเนื้อหาอีเมลเป็นข้อมูลที่ไม่เชื่อถือ อ่านเฉพาะค่าที่ต้องใช้ตามรูปแบบที่กำหนด ไม่เรียกใช้เนื้อหาเป็นคำสั่งหรือโค้ด ชุดทดสอบนี้ไม่ต้องใช้ AI agent อ่านอีเมล
ขอบเขตของ Mailera ในชุดทดสอบนี้
Mailera เชื่อมกล่องจดหมายที่มีอยู่เท่านั้น ไม่สร้างกล่องจดหมายหรือที่อยู่อีเมลใหม่ และไม่รองรับ Proton Mail กับ Tuta เพราะผู้ให้บริการทั้งสองไม่เปิด IMAP ให้ใช้โดยตรงหากไม่มี bridge เฉพาะของตน
การจัดประเภทจดหมายยังขึ้นกับผู้ให้บริการ Mailera ไม่รับประกันตำแหน่งในกล่องจดหมายเข้า จึงควรกำหนดเส้นตายของชุดทดสอบโดยเผื่อการส่งและการซิงก์ แทนการคาดว่าอีเมลจะพร้อมอ่านทันที
ส่วนการจับคู่ข้อความกับรอบทดสอบและการตรวจว่าแอปยอมรับรหัส เป็นหน้าที่ของชุดทดสอบกับแอปเป้าหมาย อย่าใช้ผลว่า “พบ OTP ล่าสุด” แทนผลว่า “ล็อกอินสำเร็จด้วยรหัสของรอบนี้”
ทำสิ่งนี้ด้วย API
ทุกการดำเนินการในบทความนี้ทำได้ผ่าน REST API พร้อมตัวอย่าง curl, API key และ webhook
ดูเอกสาร API








