123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- package mailbox
- import (
- "encoding/json"
- "time"
- "github.com/knadh/go-pop3"
- "github.com/knadh/listmonk/models"
- )
- // POP represents a POP mailbox.
- type POP struct {
- opt Opt
- client *pop3.Client
- }
- // NewPOP returns a new instance of the POP mailbox client.
- func NewPOP(opt Opt) *POP {
- return &POP{
- opt: opt,
- client: pop3.New(pop3.Opt{
- Host: opt.Host,
- Port: opt.Port,
- TLSEnabled: opt.TLSEnabled,
- TLSSkipVerify: opt.TLSSkipVerify,
- }),
- }
- }
- // Scan scans the mailbox and pushes the downloaded messages into the given channel.
- // The messages that are downloaded are deleted from the server. If limit > 0,
- // all messages on the server are downloaded and deleted.
- func (p *POP) Scan(limit int, ch chan models.Bounce) error {
- c, err := p.client.NewConn()
- if err != nil {
- return err
- }
- defer c.Quit()
- // Authenticate.
- if p.opt.AuthProtocol != "none" {
- if err := c.Auth(p.opt.Username, p.opt.Password); err != nil {
- return err
- }
- }
- // Get the total number of messages on the server.
- count, _, err := c.Stat()
- if err != nil {
- return err
- }
- // No messages.
- if count == 0 {
- return nil
- }
- if limit > 0 && count > limit {
- count = limit
- }
- // Download messages.
- for id := 1; id <= count; id++ {
- // Download just one line of the body as the body is not required at all.
- m, err := c.Top(id, 1)
- if err != nil {
- return err
- }
- var (
- campUUID = m.Header.Get(models.EmailHeaderCampaignUUID)
- subUUID = m.Header.Get(models.EmailHeaderSubscriberUUID)
- date, _ = time.Parse("Mon, 02 Jan 2006 15:04:05 -0700", m.Header.Get("Date"))
- )
- if campUUID == "" || subUUID == "" {
- continue
- }
- if date.IsZero() {
- date = time.Now()
- }
- // Additional bounce e-mail metadata.
- meta, _ := json.Marshal(struct {
- From string `json:"from"`
- Subject string `json:"subject"`
- MessageID string `json:"message_id"`
- DeliveredTo string `json:"delivered_to"`
- Received []string `json:"received"`
- }{
- From: m.Header.Get("From"),
- Subject: m.Header.Get("Subject"),
- MessageID: m.Header.Get("Message-Id"),
- DeliveredTo: m.Header.Get("Delivered-To"),
- Received: m.Header.Map()["Received"],
- })
- select {
- case ch <- models.Bounce{
- Type: "hard",
- CampaignUUID: m.Header.Get(models.EmailHeaderCampaignUUID),
- SubscriberUUID: m.Header.Get(models.EmailHeaderSubscriberUUID),
- Source: p.opt.Host,
- CreatedAt: date,
- Meta: json.RawMessage(meta),
- }:
- default:
- }
- }
- // Delete the downloaded messages.
- for id := 1; id <= count; id++ {
- if err := c.Dele(id); err != nil {
- return err
- }
- }
- return nil
- }
|