Récemment, j'ai été confronté à un problème étrange (pas vraiment). Alors que depuis des années le transfert de mail est quelque chose de fréquent, un utilisateur est venu me signaler qu'il ne recevais pas certains mails.

Heureusement, il était capable de reproduire le comportement, ce qui m'a aidé mettre en évidence ...

L'erreur

Nous sommes donc dans le cas où une personne (someone@oneone.unk) souhaite contacter mon utilisateur (user@service.my), mais mon utilisateur préfère que ses mails soient redirigés vers une addresse qui lui appartient déjà (user@personal.tld).

En regardant les journaux sur mx.service.my, je vois que personal.tld refuse la transmission du mail avec un message très explicite

> not SPF authorized sender (softfail)

Ha.

Effectivement, le SPF de oneone.unk indique :

me@localhost$ dig TXT oneone.unk +short
"v=spf1 mx ~all"

Bon, ça me fait un peu rager quand un ~ est traité comme un -, mais bon.

Maintenant qu'on sait quoi, il faut trouver pourquoi et là, rien de mieux que de regarder du côté de ...

L'infra

Et c'était tout bête en fait (pas du tout, je simplifie), mais la redirection des mails était gérée de façon très simple :

/etc/postfix/main.cf

virtual_maps = hash:/etc/postfix/redirections

/etc/postfix/redirections

user    user@personal.tld

Nous avons assez d'éléments pour dresser le portrait de ...

La cause

Cette config était totalement valable dans les années 90, mais aujourd'hui, avec les outils de réputation c'est... A vos risques et périls dirons nous. Oui, ce n'est pas aussi définitif qu'on pourrait le croire parce qu'entre les serveurs qui ne l'implémentent pas et ceux qui l'ignorent à la réception...

personal.tld indiquant que seuls ses MX ont le droit d'envoyer des courriers en son nom, les mails que je transmet pour lui ne sont pas considérés comme étant de confiance et je cours donc le risque de voir les voir refusés.

Pour que la redirection continue d'être effective, il faut indiquer que le mail est envoyé par les serveurs de service.my afin de montrer pate blanche.

Et pour ça, il y a 36 solutions. Mais j'en ai trouvé une que je trouve élégante : ajouter simplement un header "Sender". Maintenant, voyons ...

L'implémentation

Si sur le principe, c'est assez simple, je n'ai pas trouvé de façon très intégrée de le faire.

En gros :
  • On change l'adresse de destination pour la faire transiter par un domaine virtuel (redir.service.my)
  • On ajoute un transporteur virtuel qui va gérer lui même les mails à destination de ce domaine
  • Le transporteur envoie tout à procmail, qui ajoute le header et renvoie le corrier ainsi modifié

/etc/postfix/main.cf

virtual_maps = hash:/etc/postfix/redirections
transport_maps = regexp:/etc/postfix/transport.regex

/etc/postfix/redirections

user    user@redir.service.my

/etc/postfix/transport.regex

/@redir\.service\.my$/     redir:

/etc/postfix/master.cf

# ==========================================================================
# service               type  private unpriv  chroot  wakeup  maxproc command + args
#                             (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================

redir                   unix    -     n       n       -       -       pipe flags= user=mailuser argv=/usr/bin/procmail -a ${user} /etc/postfix/redirs.rc

/etc/postfix/redirs.rc

LOGFILE=/var/tmp/procmail-redirections.log
SHELL=/bin/sh
ARG=$1
SENDMAIL=/usr/sbin/sendmail
HOSTNAME=redirections.service.my
VERBOSE=yes

:0 hb
* ARG ?? ^^user^^
* ! ^X-Loop: $ARG@$HOSTNAME
| formail -A"X-Loop: $ARG@$HOSTNAME" -I"Sender: redirections@service.my" \
| $SENDMAIL -oi user@personal.tld

Bien entendu on oublie pas postmap et de recharger la config.

Bon, tout n'est pas "parfait" puisqu'on a pas mal de travail "manuel" à faire. Pour chaque redirection il faut copier un bloc dans la conf procmail, c'est pas ce qui est le plus funky. Mais bon, vu qu'il n'y a que 2 choses qui change (le nom d'utilisateur et l'adresse vers laquelle on redirige), c'est assez simple d'automatiser la chose depuis la base utilisateurs, comme c'était le cas avant.

Mais ça, ça dépend de mon archi :)