Tim HR sebelumnya mengirim email ulang tahun karyawan secara manual. Setiap hari mereka perlu memeriksa daftar tanggal lahir, mencari foto karyawan, menempelkannya ke desain Canva, kemudian mengirim hasilnya melalui email.

Proses tersebut terlihat sederhana, tetapi bergantung pada orang yang mengingat dan sempat mengerjakannya. Email bisa terlambat atau terlewat ketika pekerjaan lain sedang banyak. Saya kemudian membuat sistem yang mengerjakan proses tersebut secara otomatis melalui satu perintah PHP.

Mempertahankan Excel sebagai sumber data

Data awal yang saya terima sudah berbentuk Excel. Karena Excel masih mudah dipelihara oleh tim internal dan jumlah datanya tidak besar, saya memilih untuk tetap menggunakannya sebagai sumber utama.

Format data yang dipakai berisi:

  • Nama karyawan.
  • Departemen.
  • Tanggal lahir.
  • Foto pilihan jika nama file perlu ditentukan secara manual.
  • Status aktif jika tersedia.
  • Tanggal pengiriman email.

Pilihan ini membuat sistem lebih sederhana karena tidak membutuhkan database, dashboard, atau halaman pengelolaan karyawan baru. File Excel dipelihara oleh tim IT di server, sehingga risiko perubahan file ketika proses sedang berjalan juga lebih mudah dikendalikan.

Kolom Tanggal Kirim Email berfungsi sebagai penanda bahwa ucapan pada tahun tersebut sudah berhasil dikirim. Ketika memasuki tahun berikutnya, karyawan yang sama dapat diproses kembali.

Menangani foto yang belum rapi

Folder foto dari HR memiliki nama file yang tidak selalu sama persis dengan nama di Excel. Beberapa nama memakai nama panggilan, singkatan, tambahan nomor karyawan, atau susunan kata yang berbeda.

Script membuat indeks nama foto dengan mengabaikan kapital, tanda baca, dan tambahan nomor tertentu. Untuk hasil yang ambigu, Excel menyediakan kolom Foto agar file yang benar dapat dipilih secara eksplisit.

Saya sengaja tidak memakai pencocokan fuzzy saat pengiriman nyata. Pencocokan yang terlalu longgar dapat mengambil foto orang yang salah, dan kesalahan seperti itu lebih buruk daripada melewatkan satu orang.

Jika foto hilang, rusak, atau ambigu, karyawan tersebut tidak dimasukkan ke kartu. Masalahnya dicatat di log agar dapat diperbaiki, lalu sistem akan memeriksanya kembali pada jadwal berikutnya.

Foto mentah juga memiliki latar belakang yang berbeda-beda. Karena itu, saya membuat proses Python terpisah untuk menghapus latar belakang secara massal. Hasilnya disimpan sebagai PNG transparan di folder baru tanpa menimpa foto asli. Pemisahan ini memudahkan pemeriksaan visual sebelum foto digunakan oleh sistem email.

Membentuk kartu secara otomatis

Desain dasar dibuat di Canva dan diekspor sebagai template.png. PHP kemudian menempelkan foto, nama, departemen, dan tanggal ulang tahun pada posisi yang sudah ditentukan.

Satu kartu memuat maksimal lima karyawan. Formasinya mengikuti jumlah orang:

  • Satu sampai tiga orang memakai satu baris.
  • Empat orang memakai formasi dua di atas dan dua di bawah.
  • Lima orang memakai formasi tiga di atas dan dua di bawah.

Setiap baris dihitung dari titik tengah agar susunan kanan dan kiri tetap simetris. Jika ada lebih dari lima karyawan, sistem membuat kartu berikutnya. Semua kartu tetap dikirim dalam satu email.

Bagian nama menggunakan DM Sans Bold agar mendekati desain Canva. Label diletakkan di atas bidang gelap dengan sudut membulat, sementara elemen garis dekoratif berada di belakang label. Footer email memuat salam, nama departemen, logo perusahaan, informasi kontak, dan gambar promosi yang sudah disediakan.

Menentukan siapa yang dikirim

Scheduler tidak hanya mencari ulang tahun pada tanggal ketika perintah dijalankan.

Ulang tahun pada hari Sabtu dan Minggu ditahan dan digabung ke email hari Senin. Jika server mati pada tanggal tertentu, ulang tahun yang terlewat akan digabung dengan tanggal berikutnya ketika server kembali berjalan.

Tanggal 29 Februari hanya diproses pada tahun kabisat. Sistem tidak memindahkannya secara otomatis ke 28 Februari atau 1 Maret.

Di server production, perintah dijadwalkan pada pukul 08.00, 09.00, dan 10.00 dalam zona waktu Asia/Jakarta. Pengulangan jadwal ini menjadi mekanisme retry. Jika pengiriman pukul 08.00 gagal, kolom tanggal kirim masih kosong sehingga sistem dapat mencoba kembali pada pukul berikutnya.

Mencegah email terkirim dua kali

Alur pengiriman terdiri dari beberapa tahap:

  1. Sistem mencatat bahwa proses pengiriman dimulai.
  2. Email dikirim melalui SMTP.
  3. Penerimaan SMTP dicatat.
  4. Excel diperbarui dengan waktu pengiriman.
  5. Penyelesaian proses dicatat di log.

Setelah Excel berisi tanggal pengiriman untuk tahun berjalan, jadwal berikutnya akan melewati karyawan tersebut.

Ada satu kondisi yang tetap perlu diperhatikan. Server dapat berhenti sesaat setelah SMTP menerima email tetapi sebelum Excel berhasil diperbarui. Sistem menandai kondisi seperti ini sebagai UNKNOWN dan menahan pengiriman ulang otomatis.

Setiap kumpulan pengiriman memakai Message-ID yang stabil. Administrator dapat mencarinya pada sistem email, kemudian menetapkan apakah kejadian tersebut sudah terkirim atau boleh dicoba kembali.

Menggunakan file log tanpa database

Log operasional disimpan sebagai file teks biasa di folder logs. Isinya mencakup proses membaca Excel, foto yang hilang, percobaan SMTP, email yang diterima server, perubahan Excel, serta error konfigurasi atau file.

Sebelum memperbarui Excel, sistem juga membuat salinan cadangan. File hasil perubahan dibuka kembali dan diperiksa sebelum menggantikan file utama.

Pendekatan ini sesuai dengan skala kebutuhan saat ini. Tim tidak memerlukan database hanya untuk melihat riwayat proses, sementara file log masih mudah dibaca langsung atau melalui perintah yang sudah disediakan.

Membuat mode pengujian yang aman

Pengiriman nyata tidak boleh dijalankan menggunakan tanggal palsu. Jika diperbolehkan, seseorang dapat tanpa sengaja mengubah penanda pada Excel production menggunakan data simulasi.

Sebagai gantinya, sistem menyediakan dua mode pemeriksaan.

Mode preview membuat kartu, HTML email, dan laporan tanpa mengirim email atau mengubah Excel. Mode test email mengirim hasil simulasi ke alamat penguji dan membuat salinan Excel terpisah yang menunjukkan perubahan kolom tanggal kirim.

Dengan cara ini saya dapat memastikan tampilan email, pengiriman SMTP, pembentukan beberapa kartu, dan pembaruan Excel tanpa memengaruhi data production.

Hasil dan batasan

Sistem akhirnya tetap menggunakan komponen yang sudah dekat dengan proses kerja awal: Excel, folder foto, template dari Canva, dan email perusahaan. PHP menghubungkan semuanya melalui satu entry point CLI, sementara modul di belakangnya memisahkan pembacaan data, penjadwalan, foto, rendering kartu, SMTP, dan log.

Pengujian otomatis saat ini menjalankan 46 pemeriksaan. Cakupannya meliputi aturan akhir pekan, server yang sempat mati, tahun kabisat, layout kartu, foto rusak, beberapa kartu dalam satu email, retry, perubahan Excel, backup, status UNKNOWN, respons SMTP, dan gambar yang disematkan ke email.

Bagian yang masih bergantung pada lingkungan perusahaan adalah konfigurasi Exchange. Jika alamat pengirim berbeda dari akun SMTP, akun tersebut harus memperoleh izin Send As. Nama pengirim juga dapat ditampilkan berbeda oleh Outlook karena Outlook menggunakan informasi kontak dari Exchange, sedangkan Gmail cenderung menampilkan nama pada header email.

Pelajaran

Keputusan paling penting dalam proyek ini bukan pemilihan library, melainkan menjaga ruang lingkup sistem tetap sesuai kebutuhan.

Excel sudah cukup sebagai sumber data dan penanda keberhasilan karena file production dipelihara oleh IT. File log sudah cukup untuk menelusuri masalah. Proses penghapusan latar belakang foto lebih aman dibuat terpisah karena hasilnya perlu diperiksa manusia.

Saya juga belajar bahwa otomatisasi email bukan hanya soal menjadwalkan perintah. Sistem perlu memikirkan email ganda, kegagalan di tengah proses, akhir pekan, server yang tidak selalu hidup, data foto yang tidak konsisten, serta perbedaan perilaku antara layanan email.

Dengan menangani kondisi tersebut sejak awal, pekerjaan manual HR dapat dikurangi tanpa menambahkan sistem administrasi baru yang nantinya juga harus dipelihara.