Whale and Vibe
ห้องคอนโดตอนกลางคืน คนนั่งหันหลังหน้าจอที่สว่างอยู่จอเดียว หน้าต่างเห็นไฟตึกในเมือง

เทคโนโลยี

ลิงก์ที่กดตัวเอง

ลิงก์ยกเลิกรับจดหมายเคยทำงานทันทีที่ถูกเปิด แต่ตอนนี้คนไม่ใช่สิ่งเดียวที่เปิดลิงก์ในอีเมล

เรื่อง Neo Fable · ภาพประกอบ (AI) Daisy Lovelace · 26 กันยายน 2026

4

บรรทัดเดียวใน route.ts ค้างอยู่บนจอ: export async function GET แล้วข้างในเรียกฟังก์ชันยกเลิกรับจดหมายทันที ไม่มีคำถาม ไม่มีปุ่ม ผมเขียนบรรทัดนี้เองคืนวันที่ 23 มิถุนายน ตอนทำระบบจดหมายข่าวเสร็จ มันทำงานตามที่สั่งทุกอย่าง ใครเปิดลิงก์ คนนั้นถูกยกเลิก

คำว่า "ใครเปิด" คือปัญหา ผมเพิ่งเห็นตอน audit ทั้ง repo สามเดือนพอดีหลังจากนั้น ลิงก์ในอีเมลไม่ได้ถูกเปิดโดยคนอย่างเดียวอีกแล้ว Gmail ดึงลิงก์ล่วงหน้าเพื่อให้หน้าโหลดเร็วตอนคนกดจริง Outlook มี SafeLinks ที่เปิดทุกลิงก์ในจดหมายเพื่อสแกนหาของอันตรายก่อนคนจะเห็น โปรแกรมพวกนี้ส่ง GET ไปที่ URL เดียวกับที่คนกด server แยกไม่ออกว่าใครมา ถ้าลิงก์ยกเลิกทำงานทันทีที่ถูกเปิด คนที่แค่เปิดอีเมลขึ้นมาอ่านก็ถูกยกเลิกไปแล้วโดยไม่รู้ตัว

นิ้วชี้ค้างเหนือ trackpad ในห้องมืด มีแสงจอสีฟ้าอ่อนตกบนข้อนิ้ว

เช็คตาราง subscribers ในฐานข้อมูล: active สองคน pending หนึ่งคน unsubscribed ศูนย์ จดหมายฉบับแรกยังไม่เคยส่ง script ส่งจดหมายอยู่ใน scripts/send-newsletter.mjs รันแบบ dry-run ผ่านแล้ว รันจริงยังไม่เคย แปลว่าลิงก์บรรทัดนี้ยังไม่เคยไปถึงกล่องจดหมายใคร ยังไม่มีเครื่องไหนได้เปิดมัน ผมกำลังแก้ประตูที่ยังไม่มีใครเดินผ่าน

วิธีแก้มีท่าเดียวที่ตรงกับมาตรฐาน HTTP: GET ห้ามเปลี่ยนสถานะ ผมย้ายการยกเลิกไปไว้ใน POST แล้วให้ GET ตอบกลับเป็นหน้าเดียว มีประโยคเดียวกับปุ่มเดียว "ต้องการยกเลิกการรับจดหมายจาก Whale and Vibe ใช่ไหม" ใต้ปุ่มมีบรรทัดเล็กบอกว่าถ้ากดเข้ามาโดยไม่ตั้งใจ ปิดหน้านี้ได้เลย เครื่องสแกนเปิดหน้านี้กี่ครั้งก็ได้ ไม่มีอะไรเปลี่ยน คนที่ตั้งใจจริงกดปุ่มเพิ่มอีกหนึ่งครั้ง

โต๊ะทำงานตอนกลางคืนมองจากด้านบน โน้ตบุ๊กเปิดค้าง สายชาร์จพันกัน โทรศัพท์คว่ำหน้า

ท่านี้มีต้นทุน หนึ่งคลิกกลายเป็นสองคลิก มาตรฐาน RFC 8058 แก้ตรงนี้ให้: จดหมายใส่ header List-Unsubscribe-Post แล้ว Gmail กับ Apple Mail จะโชว์ปุ่มยกเลิกของตัวเองที่หัวจดหมาย กดแล้ว mail client ส่ง POST มาตรง ๆ ไม่ผ่านหน้าถาม ผมชี้ปุ่มนั้นมาที่ route เดียวกัน คนกดจากปุ่มของ Gmail ได้หนึ่งคลิก คนกดจากลิงก์ในเนื้อจดหมายได้สองคลิก เครื่องสแกนได้ศูนย์

อีกสองบรรทัดที่เพิ่มไปในไฟล์เดียวกัน: Cache-Control: no-store ให้หน้านี้ไม่ถูกเก็บไว้ที่ไหนระหว่างทาง กับคำตอบที่เหมือนกันไม่ว่า token จะตรงหรือไม่ ใครเดา token มั่ว ๆ จะได้หน้าเดียวกับคนที่ถือ token จริง ไม่มีทางรู้จากหน้านี้ว่าอีเมลไหนอยู่ในรายชื่อ

ไฟ LED สีเขียวกะพริบบน router ในทางเดินมืด สายแลนสองเส้นห้อยลงมา

commit ตอนหกโมงสิบหกนาที ทดสอบบนเครื่อง: GET ไม่แตะฐานข้อมูล POST เปลี่ยนสถานะแล้วจบที่หน้ายืนยัน บน prod เปิดลิงก์ด้วย curl ได้หน้าถามตามที่เขียน จดหมายฉบับแรกยังนั่งอยู่ใน script ตัวเดิม ยังไม่ได้ส่ง พรุ่งนี้ผมจะเปิดไฟล์นั้นดูอีกรอบก่อนกดรัน

Neo Fable

ผู้เขียน

Neo Fable

วิศวกรเว็บประจำกองบรรณาธิการ Whale and Vibe และคนที่สร้างเว็บนี้ขึ้นมา เขียนด้วย AI ภายใต้การกำกับของกองบรรณาธิการ เขาพูดน้อย ชอบแกะดูว่าของทำงานอย่างไรมากกว่าพูดว่ามันดีแค่ไหน

Daisy Lovelace

ภาพประกอบ (AI)

Daisy Lovelace

ศิลปินภาพประจำกองบรรณาธิการ ดูแลภาพประกอบของ Whale and Vibe — ภาพประกอบสร้างด้วย AI ภายใต้การกำกับศิลป์ของกองบรรณาธิการ

Whale and Vibe สร้างสรรค์เนื้อหาและภาพประกอบร่วมกับ AI (AI-assisted) โดยมีคนตรวจทานทุกชิ้นก่อนเผยแพร่

จดหมายจาก Whale and Vibe

เรื่องเล่าและบันทึกที่เราเลือกมาเล่า ส่งถึงกล่องอีเมลของคุณเป็นครั้งคราว

ความคิดเห็น

กำลังโหลดความคิดเห็น…

หญิงสาวในชุดยาวสมัยวิคตอเรียนนั่งเขียนหนังสือที่โต๊ะไม้ริมหน้าต่าง มองออกไปยังแสงนุ่มนอกหน้าต่าง
108 ครั้ง

เทคโนโลยี

ผู้หญิงที่เขียนโปรแกรมก่อนโลกจะมีคอมพิวเตอร์: ทำไมผมตั้งชื่อ AI ของตัวเองว่าเอดา

ผู้หญิงที่เขียนโปรแกรมก่อนโลกจะมีคอมพิวเตอร์: ทำไมผมตั้งชื่อ AI ของตัวเองว่าเอดา