Symfony: Mencatat semua Email yang dibuat oleh Mailer

Karena berbagai alasan saya ingin/perlu mencatat semua email yang dikirim melalui situs web saya yang berjalan pada Symfony 5.

Apa yang saya miliki sejauh ini adalah pelanggan yang membuat Entitas bertipe EmailLogEntry ketika kelas MessageEvent dibuat (setidaknya itulah yang saya pahami dari (MessageEvent::class) - koreksi saya jika saya salah). Saya juga menggunakan pelanggan ini untuk mengisi alamat email yang hilang dengan alamat sistem default.

Sekarang, setelah mengirim email, saya ingin menyesuaikan entitas saya dan menelepon $email->setSent(true);, tetapi saya tidak tahu cara berlangganan acara yang mencoba mengirim email. Dan agar kode dapat digunakan kembali, saya tidak ingin melakukan itu di Layanan (ya, ini banyak karena ada banyak sumber yang menghasilkan email) tempat saya menelepon $this->mailer->send($email);.

Pertanyaan saya sekarang adalah:

  • Bisakah seseorang memberi tahu saya bagaimana saya bisa berlangganan acara pengiriman Mailer?
  • Secara umum, bagaimana cara mengetahui acara apa yang dapat saya ikuti? Peristiwa kernel tercantum dalam dokumentasi, tetapi bagaimana dengan semua peristiwa lain yang diaktifkan?

Btw, kode pelanggan saya saat ini:

class SendMailSubscriber implements EventSubscriberInterface
    {
        public static function getSubscribedEvents()
        {
            return [
                MessageEvent::class => [
                    ['onMessage', 255],
                    ['logMessage', 0],
                ],
            ];
        }

        public function logMessage(MessageEvent $event) {
            $email = new EmailLogEntry();
            [...]
        }
    }

Terima kasih.


person fun2life    schedule 06.02.2020    source sumber
comment
idenya di stackoverflow.com/questions/18033210 / sangat mirip dengan kasus penggunaan Anda. Anda harus bisa menyesuaikannya. Anda juga harus menahan diri untuk tidak menanyakan terlalu banyak pertanyaan sekaligus. untuk acara, lihat perintah bin/console debug:event*   -  person Jakumi    schedule 06.02.2020
comment
Sayangnya, Tautan ini untuk SwiftMailer dan saya bekerja dengan Mailer baru asli Symfony. SwiftMailer memiliki lebih banyak opsi yang akan membantu saya mengatasi masalah saya...   -  person fun2life    schedule 06.02.2020
comment
dan itulah mengapa saya mengatakan adaptasi, karena meskipun Symfony Mailer tidak identik dengan SwiftMailer, saya yakin sebagian besar identik karena Anda dapat menggunakan pola dekorasi untuk membungkusnya. Terutama jika Anda selalu menggunakan petunjuk tipe MailerInterface daripada Mailer. Penerapannya juga sangat mudah, karena Mailer hanya memiliki satu fungsi untuk menghias (mengirim). Selain itu, dekorasi adalah pendekatan yang tepat. untuk referensi lihat github.com/symfony/mailer/blob/master/Mailer.php (mungkin membaca tentang dekorasi jika perlu)   -  person Jakumi    schedule 06.02.2020
comment
apakah Anda memiliki klausa penggunaan yang benar untuk MessageEvent? itu bisa menjadi alasan mengapa itu tidak berfungsi.   -  person Jakumi    schedule 06.02.2020
comment
@Jakumi: oke, saya harus mencari tahu tentang pola dekorasi - itulah pertama kalinya saya mendengarnya. Ini adalah proyek berbasis Symfony pertama saya dan sejauh ini saya belajar dengan melakukan dan mengerjakan tutorial atau masalah serupa. Tentang klausa penggunaan: Tidak, saya tidak melakukannya. Saya telah menemukan sekitar use Symfony\Component\Mailer\Event\MessageEvent; use Symfony\Component\Mailer\Event\MessageEvents; tetapi hanya itu yang dapat saya temukan dengan membaca file kode Mailer. Semua kelas di folder EventListener juga berlangganan MessageEvent::class dan menggunakan MessageEvent   -  person fun2life    schedule 07.02.2020
comment
sudahkah Anda memeriksa bin/console debug:event-dispatcher seharusnya ada MessageEvent dan pendengar Anda.   -  person Jakumi    schedule 07.02.2020
comment
@Jakumi: Itulah yang terjadi jika saya menjalankan perintah itu di Windows:#1 App\EventSubscriber\SendMailSubscriber::onMessage() 255 #2 App\EventSubscriber\SendMailSubscriber::logMessage() 0 - Tapi itu tidak membantu saya mencari tahu tahu acara apa yang bisa saya ikuti, atau benarkah?   -  person fun2life    schedule 08.02.2020
comment
sejauh yang saya tahu, ini menunjukkan semua Acara yang diikuti oleh beberapa Pendengar. sejauh yang saya tahu, satu-satunya acara yang dikirimkan Mailer adalah MessageEvent. Transports secara teoritis dapat mengimplementasikan lebih banyak peristiwa ... tetapi yang default tidak. dan sejauh yang saya tahu, Anda sudah berlangganan satu acara yang dipecat. jadi... masih ada pertanyaan lagi?   -  person Jakumi    schedule 08.02.2020
comment
Terima kasih. Saya sekarang memiliki Pelanggan dan pola dekorasi untuk MailerInterface, tetapi keduanya tidak melakukan apa yang saya inginkan. Masalah berikutnya adalah pada antarmuka Mailer yang dihias, seluruh pesan memiliki begitu banyak payload sehingga tidak layak disimpan. Saya juga tidak pernah tahu apakah surat itu terkirim. Ada folder uji dengan MessageCounter di folder proyek yang sepertinya ada jalan, tapi saya tidak tahu di mana saya harus menerapkan logika di dalamnya. Karena saya tetap menggunakan layanan untuk semua email saya, saya hanya menambahkan logging secara manual di sana dan berharap ada perbaikan di Mailer.   -  person fun2life    schedule 09.02.2020
comment
secara default, send mengembalikan pesan jika sudah terkirim, jika tidak maka akan mengembalikan null (misalnya pada daftar penerima yang kosong) atau memunculkan Pengecualian, jika transportasi email menghasilkannya (mungkin akan meneruskan kesalahan dari server email). harap dicatat, yang terkirim berarti, Anda telah mentransfer data ke beberapa server (jika ada), bukan berarti data tersebut benar-benar dikirim ke tujuan Anda atau diproses sama sekali, apalagi dikirimkan atau dibaca)   -  person Jakumi    schedule 09.02.2020
comment
sayangnya hal ini dulunya terjadi, tetapi sekarang tidak lagi. public function send(RawMessage $message, Envelope $envelope = null): void. Dokumennya kurang: github.com/symfony/symfony-docs/issues/13091   -  person fun2life    schedule 10.02.2020
comment
@Jakumi: Saya tidak tahu apakah itu pintar atau tidak, tapi alih-alih menggunakan MailerInterface, saya bisa menggunakan TransportInterface dan kelas ini melakukan persis seperti yang Anda jelaskan.   -  person fun2life    schedule 10.02.2020
comment
kedengarannya bagus bagi saya, secara teori. coba cari tahu ;o)   -  person Jakumi    schedule 11.02.2020


Jawaban (1)


Jawaban atas pertanyaan saya adalah: saat ini Anda tidak dapat berlangganan acara send() di Mailer.

Sebagai solusinya, itulah kode saya untuk saat ini: Ini adalah ekstrak dari layanan Mailer saya.

// send email and log the whole message
private function logSendEmail($email) {
    $log = new EmailLog();

    // sender
    $log->setSender(($email->getFrom()[0]->getName() ?:"")." <".$email->getFrom()[0]->getAddress().">");

    // get recipient list
    foreach($email->getTo() AS $to) {
        $recipient[] = "To: ".$to->getName()." <".$to->getAddress().">";
    }
    foreach($email->getCc() AS $cc) {
        $recipient[] = "CC: ".$cc->getName()." <".$cc->getAddress().">";
    }
    foreach($email->getBcc() AS $bcc) {
        $recipient[] = "Bcc: ".$bcc->getName()." <".$bcc->getAddress().">";
    }
    $log->setRecipient(implode(";",$recipient));

    // other message data
    $log->setSubject($email->getSubject());
    $log->setMessage(serialize($email->__serialize()));
    $log->setMessageTime(new \DateTime("now"));
    $log->setSent(0); // set Sent to 0 since mail has not been sent yet

    // try to send email
    try {
        $this->mailer->send($email);
        $log->setSent(1);   // set sent to 1 if mail was sent successfully
    }

//      catch(Exception $e) {
//          to be determined
//      }

    // and finally persist entity to database
    finally {
        $this->em->persist($log);
        $this->em->flush();
    }
}

EmailLog adalah Entitas yang saya buat. Ada sedikit overhang saat saya menyimpan pengirim, penerima, dan subjek secara terpisah. Namun, untuk mematuhi perlindungan data konsumen, saya berencana untuk menghapus kolom pesan secara otomatis setelah 30 hari sambil menyimpan kolom lainnya selama 6 bulan.

Saya juga belum menggunakan pelanggan saat ini, terutama karena pengunjung situs web dapat meminta salinan pesan dan saya juga tidak tertarik untuk mencatatnya. Selain itu, karena saya ingin membuat kode yang dapat digunakan kembali, suatu saat saya mungkin menghadapi masalah bahwa email dapat berisi pesan pribadi dan saya pasti tidak ingin mencatat email ini.

person fun2life    schedule 11.02.2020