J'utilise un serveur Ubuntu 14.04 (Linux). J'ai installé et configuré Postfix et OpenDKIM très bien sur le serveur; Je peux me envoyer des courriels à des commandes telles que echo hi | sendmail root
, et postfix / opendkim ajouterai - têtes tels que Message-Id
, Date
et DKIM-Signature
, avant l'e - mail à mon adresse e - mail personnelle, et tout fonctionne très bien.
Maintenant, je voudrais créer une application qui s'exécute dans un conteneur Docker et peut envoyer des e-mails avec la même facilité. En particulier, je ne veux pas m'inquiéter d'ajouter des en-têtes comme Message-Id
, et je ne veux pas faire beaucoup de configuration ou d'installation de logiciels à l'intérieur du conteneur lui-même.
Quelle est la meilleure façon de procéder?
Existe-t-il un moyen de laisser le conteneur exécuter l' sendmail
exectuable sur l'hôte?
J'ai essayé d'établir une connexion à Postfix à partir d'un conteneur en utilisant le protocole SMTP sur le port 25, mais Postfix semble traiter les messages reçus de cette manière différemment; Je pense qu'il n'a ajouté aucun en-tête, le message a donc été rejeté comme spam par gmail (il n'était même pas assez bon pour être placé dans mon dossier Spam).
Voici le contenu du maillog
Sep 28 23:35:52 dantooine postfix/smtpd[4306]: connect from unknown[172.17.0.95]
Sep 28 23:35:52 dantooine postfix/smtpd[4306]: DD457889B: client=unknown[172.17.0.95]
Sep 28 23:35:52 dantooine postfix/cleanup[4309]: DD457889B: message-id=<>
Sep 28 23:35:52 dantooine spamd[3175]: spamd: connection from localhost [::1]:59471 to port 783, fd 6
Sep 28 23:35:52 dantooine spamd[3175]: spamd: handle_user (getpwnam) unable to find user: 'someone'
Sep 28 23:35:52 dantooine spamd[3175]: spamd: still running as root: user not specified with -u, not found, or set to root, falling back to nobody
Sep 28 23:35:52 dantooine spamd[3175]: spamd: processing message (unknown) for someone:65534
Sep 28 23:35:52 dantooine spamd[3175]: spamd: clean message (2.5/5.0) for someone:65534 in 0.0 seconds, 331 bytes.
Sep 28 23:35:52 dantooine spamd[3175]: spamd: result: . 2 - MISSING_DATE,MISSING_FROM,MISSING_MID,UNPARSEABLE_RELAY scantime=0.0,size=331,user=someone,uid=65534,required_score=5.0,rhost=localhost,raddr=::1,rport=59471,mid=(unknown),autolearn=no autolearn_force=no
Sep 28 23:35:52 dantooine opendkim[3179]: DD457889B: can't determine message sender; accepting
Sep 28 23:35:53 dantooine postfix/qmgr[3664]: DD457889B: from=<[email protected]>, size=275, nrcpt=1 (queue active)
Sep 28 23:35:53 dantooine postfix/smtpd[4306]: disconnect from unknown[172.17.0.95]
Sep 28 23:35:53 dantooine postfix/smtp[4311]: DD457889B: to=<[email protected]>, relay=gmail-smtp-in.l.google.com[2607:f8b0:4003:c05::1b]:25, delay=0.25, delays=0.12/0.01/0.03/0.09, dsn=5.7.1, status=bounced (host gmail-smtp-in.l.google.com[2607:f8b0:4003:c05::1b] said: 550-5.7.1 [fd17:8b70:893a:44bf:fe73:6c21] Our system has detected that 550-5.7.1 this message is likely unsolicited mail. To reduce the amount of spam 550-5.7.1 sent to Gmail, this message has been blocked. Please visit 550-5.7.1 http://support.google.com/mail/bin/answer.py?hl=en&answer=188131 for 550 5.7.1 more information. su20si7357528oeb.94 - gsmtp (in reply to end of DATA command))
Sep 28 23:35:53 dantooine postfix/cleanup[4309]: 254E688A0: message-id=<[email protected]>
Sep 28 23:35:53 dantooine postfix/bounce[4330]: DD457889B: sender non-delivery notification: 254E688A0
Sep 28 23:35:53 dantooine postfix/qmgr[3664]: 254E688A0: from=<>, size=3374, nrcpt=1 (queue active)
Sep 28 23:35:53 dantooine postfix/qmgr[3664]: DD457889B: removed
Sep 28 23:35:53 dantooine postfix/virtual[4331]: 254E688A0: to=<[email protected]>, relay=virtual, delay=0.01, delays=0/0/0/0, dsn=2.0.0, status=sent (delivered to maildir)
Sep 28 23:35:53 dantooine postfix/qmgr[3664]: 254E688A0: removed
To
tête, un en-Subject
tête et un corps d'une ligne. Je ne sais pas comment dire quels en-têtes il avait après que Postfix l'ait parcouru les milters, savez-vous comment? Voici la sortie dans / var / log / syslog montrant comment il a été traité par Postfix et refusé par Gmail: gist.github.com/DavidEGrayson/fbf65c8290c049a1f262Réponses:
Parce que vous avez une solution qui fonctionne, j'essaierai ici d'expliquer différents comportements lorsque vous vous connectez telnet à postfix (SMTP) et lorsque vous utilisez sendmail (non-SMTP).
Pour info, OpenDKIM sera invoqué par postfix avec le mécanisme Milter . Vous pouvez obtenir des informations sur l'implémentation plus douce de postfix via cette documentation officielle . Voici le schéma du crochet milter en suffixe.
Vous pouvez voir que sendmail-way (non-SMTP) et telnet-way (SMTP) ont un ordre de traitement différent.
L'e-mail non SMTP sera traité par nettoyage avant d'être injecté à milter. Démon de nettoyage était responsable de l' ajout des en- têtes manquants: (Resent-) De :, A :, Message-Id :, et Date: . Par conséquent, votre e-mail aura un en-tête complet lorsqu'il sera injecté dans OpenDKIM milter, même l'e-mail d'origine avait un en-tête incomplet.
L'e-mail SMTP sera injecté dans OpenDKIM milter avant tout traitement de nettoyage. Par conséquent, si votre e-mail d'origine avait un en-tête incomplet, opendkim peut refuser de signer l'e-mail. L'en - tête From: était obligatoire (voir RFC 6376 ) et si un e-mail ne l'a pas, OpenDKIM refusera de signer l'e-mail et vous donnera un avertissement
Comme je n'utilise jamais docker, je ne sais pas quelle limitation sur sendmail / pickup à l'intérieur d'un conteneur. Je pense que la solution de contournement de David Grayson était suffisamment sûre pour s'assurer qu'OpenDKIM signait le message.
la source
From:
tête dans votre e-mail :)Message-Id
je ne sais pas grand-chose et je me tromperais probablement ... il semble plus facile de laisser le démon de nettoyage s'en occuper.From
tête. Mais, si vous voulez générer votre propre Message-ID, vous pouvez utiliser une recommandation comme celle-ci IETF DraftVous devez pointer
inet_interfaces
vers docker bridge (docker0
) dans la configuration postfix située sur le set/etc/postfix/main.cf
Plus de détails de travail internes lors de l' envoi d'un e-mail à partir de Docker via Postfix installé sur l'hôte
la source
172.17.0.0/16
àmynetworks
dans/etc/postfix/main.cf
etservice postfix restart
.Ceci est une demi-réponse, ou au moins une demi-testée, car je travaille actuellement sur le même problème. J'espère que quelqu'un pourra aider à étoffer ce que j'ai manqué.
La réponse de l'OP (David Grayson) me semble être une réinvention de la bobine de courrier de postdrop, mais l'utilisation de cette bobine de courrier semble être une approche prometteuse, alors voici où j'en suis arrivé.
L'interface de compatibilité / usr / bin / sendmail fournie par postfix transmet le courrier à postdrop, qui est sgid postdrop, lui permettant de stocker le courrier dans la file d'attente maildrop à / var / spool / postfix / maildrop. Cela devrait se produire dans le conteneur Docker. Espérons que le reste de postfix ne doive pas s'exécuter dans le conteneur.
Donc, je suis l'hôte de montage / var / spool / postfix / maildrop et / var / spool / postfix / public. Je peux recevoir du courrier dans / var / spool / postfix / maildrop dans l'environnement hôte, car j'ai monté le répertoire de la file d'attente maildrop. Parce que j'ai monté
/var/spool/postfix/public
,maildrop
peut signalerpickup
de recueillir le courrier de la file d'attente. Malheureusement, les uids et les gids impliqués sauf si je m'occupe de cela, ce qui signifie que la collecte dans le répertoire hôte ne peut pas lire les fichiers spoule, et pire l'installation postfixe gâche les autorisations sur le répertoire maildrop dans l'environnement hôte.Pourtant, cela semble fonctionner:
Bien que cela fonctionne, je ne suis pas très content de coder en dur les uids et les gids. Cela signifie que le même conteneur ne peut pas être compté pour fonctionner de la même manière partout. Je pense cependant que si au lieu de monter le volume à partir de l'hôte, je le monte à partir d'un conteneur qui exécute postfix, alors il ne sera jamais en conflit, et je n'ai besoin que d'une seule installation postfix pour extraire le courrier de nombreux conteneurs. Je mettrais ces uids et gids dans une image de base dont tous mes conteneurs héritent.
Je me demande cependant si c'est vraiment une bonne approche. Avec une configuration de messagerie aussi simple et aucun démon utilisé sur le conteneur pour réessayer la distribution, un MTA local plus simple comme msmtp pourrait être plus approprié. Il livrerait via TCP à un relais sur le même hôte, où la mise en file d'attente se produirait.
Les préoccupations concernant l'approche msmtp comprennent:
En général, l'approche du spool postfix partagé semble plus susceptible d'être une configuration fragile à installer, mais moins susceptible d'échouer au moment de l'exécution (relais indisponible, donc courrier abandonné).
la source
J'ai décidé que la façon dont le conteneur enverra le courrier consiste à l'écrire dans un fichier dans un répertoire particulier, qui sera accessible à la fois depuis le conteneur et l'hôte en tant que "volume" Docker.
J'ai créé un script shell appelé mailsender.sh qui lit les mails d'un répertoire spécifié, les envoie à sendmail, puis les supprime:
Ubuntu utilise upstart, j'ai donc créé un fichier nommé
/etc/init/mailsender.conf
pour transformer ce script en démon:Je peux démarrer le service avec
start mailsender
et l'arrêter avecstop mailsender
. Je peux regarder ses journaux/var/log/upstart/mailsender.log
et bien sûr, je peux le surveiller en utilisant le fichier PID.Vous devez créer le
/var/mailsend
répertoire, puis le rendre accessible à partir du conteneur Docker en ajoutant l'argument-v /var/mailsend:/var/mailsend
à votredocker run
commande.la source