MarkMessageSent records that an outbound message was accepted by the relay: delivery_status='sent', the From identity actually used, and one message_recipients row per recipient (to/cc/bcc) at 'sent'. Called after a successful relay accept. Idempotent on the recipient rows.
(ctx context.Context, messageID, sentAs string, to, cc, bcc []string)
| 146 | // message_recipients row per recipient (to/cc/bcc) at 'sent'. Called after a |
| 147 | // successful relay accept. Idempotent on the recipient rows. |
| 148 | func (s *Store) MarkMessageSent(ctx context.Context, messageID, sentAs string, to, cc, bcc []string) error { |
| 149 | tx, err := s.pool.Begin(ctx) |
| 150 | if err != nil { |
| 151 | return err |
| 152 | } |
| 153 | defer tx.Rollback(ctx) |
| 154 | |
| 155 | if _, err := tx.Exec(ctx, |
| 156 | `UPDATE messages SET delivery_status = 'sent', sent_as = $2 WHERE id = $1`, |
| 157 | messageID, nullIfEmpty(sentAs), |
| 158 | ); err != nil { |
| 159 | return err |
| 160 | } |
| 161 | add := func(addrs []string, kind string) error { |
| 162 | for _, a := range addrs { |
| 163 | addr := NormalizeEmail(a) |
| 164 | if addr == "" { |
| 165 | continue |
| 166 | } |
| 167 | if _, err := tx.Exec(ctx, |
| 168 | `INSERT INTO message_recipients (id, message_id, address, kind, status) |
| 169 | VALUES ($1, $2, $3, $4, 'sent') |
| 170 | ON CONFLICT (message_id, address) DO NOTHING`, |
| 171 | "rcpt_"+generateID(), messageID, addr, kind, |
| 172 | ); err != nil { |
| 173 | return err |
| 174 | } |
| 175 | } |
| 176 | return nil |
| 177 | } |
| 178 | if err := add(to, "to"); err != nil { |
| 179 | return err |
| 180 | } |
| 181 | if err := add(cc, "cc"); err != nil { |
| 182 | return err |
| 183 | } |
| 184 | if err := add(bcc, "bcc"); err != nil { |
| 185 | return err |
| 186 | } |
| 187 | return tx.Commit(ctx) |
| 188 | } |
| 189 | |
| 190 | // --- Suppression list --- |
| 191 |