
Dalam blog ini, saya akan menjelaskan proses yang saya lalui untuk menyimpan isi email ke dalam S3 (Layanan Penyimpanan Sederhana Amazon) dan data tambahan ke dalam tabel MySQL untuk memudahkan referensi silang.
Dalam blog ini, saya akan menjelaskan proses yang saya lalui untuk menyimpan isi email ke S3 (Amazon’s Simple Store Service) dan data tambahan ke dalam tabel MySQL untuk referensi silang yang mudah. Akhirnya, ini adalah titik awal untuk basis kode yang akan mencakup aplikasi yang akan memungkinkan pencarian email yang diarsipkan dengan mudah, dan kemudian menampilkan email tersebut bersama dengan data acara (log). Kode untuk proyek ini dapat ditemukan di repositori GitHub berikut: https://github.com/jeff-goldstein/PHPArchivePlatform.
Meski saya akan memanfaatkan S3 dan MySQL dalam proyek ini, bukan berarti itu adalah satu-satunya teknologi yang dapat digunakan untuk membangun platform pengarsipan, tetapi mengingat ketersebarannya, saya pikir itu adalah pilihan yang baik untuk proyek ini. Dalam sistem skala penuh dengan volume tinggi, saya akan menggunakan basis data dengan kinerja lebih tinggi daripada MySQL, tetapi untuk proyek contoh ini, MySQL sangat cocok.
Saya telah merinci di bawah ini, langkah-langkah yang saya lakukan dalam tahap pertama dari proyek ini:
Membuat duplikat email untuk pengarsipan
Menggunakan fitur Archiving dan Inbound Relay dari SparkPost untuk mengirim salinan email asli kembali ke SparkPost untuk diproses ke dalam struktur JSON, kemudian dikirim ke pengumpul webhook (aplikasi)
Memisahkan struktur JSON untuk mendapatkan komponen yang diperlukan
Mengirim isi email ke S3 untuk penyimpanan
Mencatat entri ke MySQL untuk setiap email untuk referensi silang
Membuat Duplikat dari Email
Dalam SparkPost cara terbaik untuk mengarsipkan email adalah dengan membuat salinan identik dari email yang dirancang khusus untuk tujuan pengarsipan. Ini dilakukan dengan menggunakan fitur Arsip SparkPost. Fitur Arsip SparkPost memberi pengirim kemampuan untuk mengirim duplikat email ke satu atau lebih alamat email. Duplikat ini menggunakan pelacakan dan tautan terbuka yang sama seperti aslinya. Dokumentasi SparkPost mendefinisikan fitur Arsip dengan cara berikut:
Penerima dalam daftar arsip akan menerima replika pesan yang dikirim ke alamat RCPT TO. Secara khusus, tautan terkode yang ditujukan untuk penerima RCPT TO akan identik dalam pesan arsip.
Satu-satunya perbedaan antara salinan arsip ini dan email asli RCPT TO adalah beberapa header akan berbeda karena alamat target untuk email pengarsipan berbeda, tetapi isi email akan menjadi replika yang persis sama!
Jika Anda menginginkan penjelasan lebih mendalam, berikut adalah tautan ke dokumentasi SparkPost tentang membuat salinan duplikat (atau arsip) dari email. Contoh header X-MSYS-API untuk proyek ini ditampilkan kemudian dalam blog ini.
Ada satu pengecualian untuk pendekatan ini; sementara semua informasi acara dalam email asli diikat bersama oleh transmission_id dan message_id, tidak ada informasi dalam acara relay masuk (mekanisme untuk memperoleh dan menyebarkan email arsip) untuk email duplikat yang menghubungkan kembali ke salah satu dari dua id tersebut dan dengan demikian informasi untuk email asli. Ini berarti kita perlu menempatkan data dalam badan email dan header email asli sebagai cara untuk menghubungkan semua data SparkPost dari email asli dan arsip.
Untuk membuat kode yang ditempatkan ke dalam badan email, saya menggunakan proses berikut dalam aplikasi pembuatan email.
Di suatu tempat dalam badan email, saya menempatkan entri input berikut:<input name="ArchiveCode" type="hidden" value="<<UID>>">
Kemudian saya membuat kode unik dan mengganti bidang <<UID>>:$uid = md5(uniqid(rand(), true)); $emailBody = str_replace(“<<UID>>,$uid,$emailBody);
Berikut adalah contoh output:
<input name="ArchiveCode" type="hidden" value="00006365263145">
Selanjutnya, saya memastikan menambahkan $UID ke blok meta_data pada header X-MSYS-API. Langkah ini memastikan bahwa UID tertanam dalam setiap output acara untuk email asli:
X-MSYS-API:{ "campaign_id":"<my_campaign>", "metadata":{ "UID":"<UID>" }, "archive":[ { "email":"archive@geekwithapersonality.com" } ], "options":{ "open_tracking":false, "click_tracking":false, "transactional":false, "ip_pool":"<my_ip_pool>" } }
Sekarang kita memiliki cara untuk mengaitkan semua data dari email asli ke badan email dari arsip.
Mendapatkan versi Archive
Mendapatkan email duplikat dalam struktur JSON
Pada fase pertama proyek ini, semua yang saya simpan adalah format email rfc822 di S3 dan beberapa bidang deskripsi tingkat tinggi ke dalam tabel SQL untuk pencarian. Karena SparkPost akan mengirim data email dalam struktur JSON ke platform pengarsipan saya melalui streaming data webhook, saya membangun aplikasi (yang sering disebut sebagai collector) yang menerima data stream Relay_Webhook.
Setiap paket dari SparkPost Relay_Webhook akan berisi informasi dari satu email duplikat sekaligus, sehingga memecah struktur JSON menjadi komponen yang ditargetkan untuk proyek ini cukup sederhana. Dalam kode PHP saya, mendapatkan email berformat rfc822 semudah beberapa baris kode berikut:
if ($verb == "POST") { $body = file_get_contents("php://input"); $fields = json_decode($body, true); $rfc822body = $fields['0']['msys']['relay_message']['content']['email_rfc822']; $htmlbody = $fields['0']['msys']['relay_message']['content'][html'] $headers = $fields['0']['msys']['relay_message']['content']['headers'];}
Beberapa informasi yang ingin saya simpan ke dalam tabel SQL saya terdapat dalam array bidang header. Jadi saya menulis fungsi kecil yang menerima array header dan mengulang melalui array untuk mendapatkan data yang ingin saya simpan:
function get_important_headers($headers, &$original_to, &$headerDate, &$subject, &$from) { foreach ($headers as $key => $value) { foreach ($value as $key_sub => $value_sub) { if ($key_sub == 'To') $original_to = $value_sub; if ($key_sub == 'Date') $headerDate = $value_sub; if ($key_sub == 'Subject') $subject = $value_sub; if ($key_sub == 'From') $from = $value_sub; } } }
Sekarang setelah saya memiliki data tersebut, saya siap untuk menyimpan badan ke dalam S3.
Menyimpan email duplikat di S3
Saya minta maaf mengecewakan Anda, tetapi saya tidak akan memberikan tutorial langkah demi langkah tentang cara membuat S3 bucket untuk menyimpan email, dan saya juga tidak akan menjelaskan cara membuat kunci akses yang diperlukan dalam aplikasi Anda untuk mengunggah konten ke bucket Anda; ada tutorial yang lebih baik tentang subjek ini daripada yang pernah saya tulis. Berikut beberapa artikel yang mungkin bisa membantu:
https://docs.aws.amazon.com/quickstarts/latest/s3backup/step-1-create-bucket.html
https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/
Apa yang akan saya lakukan adalah menunjukkan beberapa pengaturan yang saya pilih yang berkaitan dengan proyek seperti ini.
Kontrol Akses. Anda tidak hanya perlu mengatur keamanan untuk bucket, tetapi Anda juga harus mengatur izin untuk item-item itu sendiri. Dalam proyek saya, saya menggunakan kebijakan sangat terbuka berupa public-read karena data sampel tidak bersifat pribadi dan saya menginginkan akses mudah ke data tersebut. Anda mungkin menginginkan serangkaian kebijakan ACL yang jauh lebih ketat. Berikut adalah artikel bagus tentang pengaturan ACL: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
Mengarsipkan Arsip. Dalam S3 ada sesuatu yang disebut Lifecycle Management. Ini memungkinkan Anda memindahkan data dari satu jenis kelas penyimpanan S3 ke yang lain. Kelas penyimpanan yang berbeda mewakili jumlah akses yang Anda butuhkan ke data yang disimpan dengan biaya lebih rendah terkait dengan penyimpanan yang Anda akses paling sedikit. Penjelasan baik tentang berbagai kelas dan peralihannya dapat ditemukan dalam panduan AWS yang disebut, Transitioning Objects. Dalam kasus saya, saya memilih untuk membuat siklus hidup yang memindahkan setiap objek dari Standard ke Glacier setelah satu tahun. Akses Glacier jauh lebih murah daripada arsip S3 standar dan akan menghemat biaya penyimpanan saya.
Setelah saya membuat S3 bucket dan pengaturan saya siap, S3 siap untuk saya mengunggah email yang mematuhi rfc822 yang saya peroleh dari aliran data SparkPost Relay Webhook. Tetapi sebelum mengunggah payload email rfc822 ke S3 saya perlu membuat nama file unik yang akan saya gunakan untuk menyimpan email tersebut.
Untuk nama file unik, saya akan mencari tubuh email untuk id tersembunyi yang ditempatkan oleh aplikasi pengirim ke dalam email dan menggunakan id tersebut sebagai nama file. Ada cara yang lebih elegan untuk menarik connectorId dari tubuh html, tetapi untuk kesederhanaan dan kejelasan saya akan menggunakan kode berikut:
$start = strpos($htmlbody, $inputField); $start = strpos($htmlbody, "value=", $start) + 7; $end = strpos($htmlbody, ">", $start) - 1; $length = $end - $start; $UID = substr($html, $start, $length);
* kami berasumsi bahwa $inputField memiliki nilai “ArchiveCode” dan ditemukan dalam file config.php saya.
Dengan UID, kita kemudian dapat membuat nama file yang akan digunakan di S3:
$fileName = $ArchiveDirectory . '/' . $UID . '.eml';
Sekarang saya bisa membuka koneksi saya ke S3 dan mengunggah file. Jika Anda melihat file s3.php di repositori GitHub, Anda akan melihat bahwa hanya sedikit kode yang diperlukan untuk mengunggah file tersebut.
Langkah terakhir saya adalah mencatat entri ini ke dalam tabel MYSQL.
Menyimpan Meta Data di MySQL
Kami telah mengambil semua data yang diperlukan pada langkah sebelumnya, jadi langkah penyimpanannya mudah. Pada fase pertama ini, saya memilih untuk membuat tabel dengan bidang-bidang berikut:
Entri field otomatis untuk tanggal/waktu
Alamat email target (RCPT_TO)
Stempel waktu dari header email DATE
Header SUBJECT
Header alamat email FROM
Direktori yang digunakan dalam bucket S3
Nama file S3 untuk email yang diarsipkan
Fungsi bernama, MySQLLog dalam file aplikasi upload.php menjalani langkah-langkah yang diperlukan untuk membuka tautan ke MySQL, menyuntikkan baris baru, menguji hasil dan menutup tautan. Saya memang menambahkan satu langkah lain untuk memastikan dan itu adalah untuk mencatat data ini ke dalam file teks. Haruskah saya melakukan lebih banyak pencatatan untuk kesalahan? Ya. Namun, saya ingin menjaga kode ini tetap ringan agar dapat berjalan dengan sangat cepat. Terkadang, kode ini akan dipanggil ratusan kali per menit dan perlu seefisien mungkin. Pada pembaruan mendatang, saya akan menambahkan kode tambahan yang akan memproses kegagalan dan mengirim email kegagalan tersebut kepada admin untuk pemantauan.
Menyelesaikannya
Jadi dalam beberapa langkah yang cukup mudah, kami dapat melalui fase pertama membangun sistem pengarsipan email yang kuat yang menyimpan duplikat email di S3 dan data cross-referencing dalam tabel MySQL. Ini akan memberikan dasar untuk proyek lainnya yang akan ditangani dalam beberapa postingan mendatang.
Dalam revisi proyek di masa depan, saya berharap untuk:
Menyimpan semua log acara dari email asli
Mengirim kesalahan penyimpanan ke admin ketika terjadi kegagalan pengunggahan atau log
Meminimalkan kompleksitas kolektor.
Menambahkan antarmuka pengguna untuk melihat semua data
Mendukung kemampuan untuk mengirim ulang email
Sementara itu, saya harap proyek ini menarik dan berguna bagi Anda; selamat mengirim.