_,err:=a.db.ExecContext(ctx,`INSERT OR IGNORE INTO send_queue(id,user_id,mailbox_id,sent_message_id,message_id,source,mail_from,header_from,recipients_json,mime_base64,status,next_attempt_at,created_at,updated_at)
iferr:=a.db.QueryRowContext(ctx,`SELECT id,status,attempt_count,max_attempts FROM send_queue WHERE mailbox_id=? AND source=? AND message_id=?`,in.MailboxID,in.Source,messageID).Scan(&existingID,&status,&attemptCount,&maxAttempts);err!=nil{
_,err:=a.db.ExecContext(ctx,`UPDATE send_queue SET user_id=?,sent_message_id=?,mail_from=?,header_from=?,recipients_json=?,mime_base64=?,status=?,attempt_count=0,next_attempt_at=?,last_error='',updated_at=?,delivered_at=NULL WHERE id=? AND status=? AND attempt_count>=max_attempts`,
rows,err:=a.db.QueryContext(ctx,`SELECT id FROM send_queue WHERE (status=? OR (status=? AND attempt_count<max_attempts)) AND next_attempt_at<=? ORDER BY next_attempt_at, created_at LIMIT 20`,sendQueueStatusQueued,sendQueueStatusFailed,a.now().UTC().Format(time.RFC3339Nano))
rows,err:=a.db.QueryContext(ctx,`SELECT id,user_id,mailbox_id,sent_message_id,message_id,source,mail_from,header_from,recipients_json,mime_base64,attempt_count,max_attempts FROM send_queue WHERE status=? AND updated_at<=? AND attempt_count<max_attempts LIMIT 20`,sendQueueStatusSending,cutoff)
res,err:=a.db.ExecContext(ctx,`UPDATE send_queue SET status=?,next_attempt_at=?,last_error=?,updated_at=? WHERE id=? AND status=?`,sendQueueStatusFailed,now,"send attempt interrupted",now,item.ID,sendQueueStatusSending)
if_,err:=a.db.ExecContext(ctx,`UPDATE send_queue SET status=?,delivered_at=?,updated_at=?,last_error='',mime_base64='' WHERE id=?`,sendQueueStatusDelivered,now,now,item.ID);err!=nil{
res,err:=a.db.ExecContext(ctx,`UPDATE send_queue SET status=?,attempt_count=attempt_count+1,updated_at=? WHERE id=? AND (status=? OR (status=? AND attempt_count<max_attempts)) AND next_attempt_at<=?`,sendQueueStatusSending,now,id,sendQueueStatusQueued,sendQueueStatusFailed,now)
iferr!=nil{
returnsendQueueItem{},err
}
ifn,_:=res.RowsAffected();n==0{
returnsendQueueItem{},sql.ErrNoRows
}
varitemsendQueueItem
varrecipientsJSON,mimeBase64string
row:=a.db.QueryRowContext(ctx,`SELECT id,user_id,mailbox_id,sent_message_id,message_id,source,mail_from,header_from,recipients_json,mime_base64,attempt_count,max_attempts FROM send_queue WHERE id=?`,id)
_,err:=a.db.ExecContext(ctx,`UPDATE send_queue SET status=?,next_attempt_at=?,last_error=?,updated_at=? WHERE id=?`,status,nextAttempt.Format(time.RFC3339Nano),sendErr.Error(),now.Format(time.RFC3339Nano),item.ID)
iferr!=nil{
a.log.Warn("failed to mark send queue failed","id",item.ID,"error",err)
_,err:=a.db.ExecContext(ctx,`INSERT INTO send_audit_events(id,queue_id,user_id,mailbox_id,sent_message_id,source,event,status,mail_from,header_from,recipients_json,error,created_at)
err:=a.db.QueryRowContext(ctx,`SELECT display_name,enabled FROM send_as_grants WHERE mailbox_id=? AND address=?`,mb.ID,from).Scan(&displayName,&enabled)
iferr==nil{
ifenabled==0{
return"","",fmt.Errorf("send-as address is disabled")
}
returnfrom,strings.TrimSpace(displayName),nil
}
if!errors.Is(err,sql.ErrNoRows){
return"","",err
}
varaliasDestinationstring
err=a.db.QueryRowContext(ctx,`SELECT destination FROM aliases WHERE source=? AND enabled=1`,from).Scan(&aliasDestination)