# envoyer un email avec pièce jointe depuis le terminal



## domi73 (27 Septembre 2015)

Bonjour,

J'ai besoin d'envoyer un email de ce type de façon transparente (sans lancer l'application Mail) par une ligne de commande.

A: boite@faxbox.se
Objet: 00331234567
Message: vide
Pièce jointe: piece.pdf

Avez-vous une idée de la meilleure manière de faire ?

Le plus proche que je suis arrivé est d'utiliser la commande CURL,:

curl --url "smtps://adresse.smtp.com:465" --ssl-reqd --mail-from "mon@mail.com" --mail-rcpt "boite@faxbox.se" --upload-file mail.txt --user "mon@mail.com:motdepasse"

Le fichier mail.txt comprend

From: "Moi" <mon@mail.com>
To: boite@faxbox.com
Subject: 00331234567

*Voici mes questions:*
- Je ne ne sais pas comment mettre la pièce jointe.

- J'aimerais éviter de devoir utiliser le fichier mail.txt pour définir l'objet de mon courriel, est-ce qu'il y a moyen de l'envoyer directement depuis la ligne de commande ?

Merci d'avance pour vos suggestions


----------



## bompi (27 Septembre 2015)

Tu peux tout faire avec les commandes en mode texte, comme convertir les pièces jointes en un format convenable pour la transmission (*base64*), constituer le corps du message avec les séparateurs _ad hoc_ et transmettre tout ça.

Pour autant, je te conseillerais plutôt d'écrire un script, par exemple en Perl, langage qui regorge de modules bien pratique pour faire tout ça. Regarde par exemple ici ou là.


----------



## domi73 (28 Septembre 2015)

Bonjour,
Merci pour ta réponse.

J'explique le problème de base: j'aimerais utiliser une solution mail to fax depuis ma base de donnée Filemaker. Filemaker permet l'envoi direct d'email depuis ses scripts via un serveur smtp (dans lequel je met mes propres données de serveur d'envoi). Le problème est que les courriels générés par Filemaker ont des entêtes qui ne fonctionnent pas avec la solution mail to fax. 
Apparemment leurs entêtes ne sont pas conventionnelles et je pense que cela vient de là, car lorsque j'envoie un courriel identique depuis l'application Mail de mac OS X cela fonctionne pparfaitement bien et le fax est bien transmis. 
Le problème que cela me pose de passer par l'application Mail est que cela rajoute une étape supplémentaire pour l'utilisateur (ouverture d'une fenêtre mail) et en plus, comme j'ai plusieurs utilisateurs, cela veut dire que l'envoi ne provient pas toujours de la même adresse email.

Concernant le script perl ou autre, le désavantage, c'est que je devrais aller l'installer sur chaque poste d'utilisateur. L'avantage, si je peux tout envoyer via une ligne de commande, c'est que j'envoie le courriel directement depuis ma solution filemaker (via applescript "do shell script") et cela est accessible de façon uniforme pour tous les utilisateurs.

Donc je recherche une commande qui me permet d'envoyer un email avec des entetes ressemblant à celles générées par l'application Mail en spécifiant directement le serveur smtp d'envoi, un numéro de fax comme objet de mail et une pièce jointe en pdf en annexe. Le corps du message doit être vide.

Voilà, je ne sais pas si j'ai été assez clair.

Tu semblais dire que cela était possible, pourrais-tu me dire de quelle manière (quelle commande, avec curl ?) ?
Merci d'avance.


----------



## Deleted member 1099514 (28 Septembre 2015)

Salut

Tu peux aussi regarder du coté des commandes :
mail
sendmail

@+


----------



## domi73 (28 Septembre 2015)

jeanjd63 a dit:


> Salut
> 
> Tu peux aussi regarder du coté des commandes :
> mail
> ...


Merci oui j'ai regardé, mais je n'ai pas réussi à envoyer en une seule ligne de commande le tout, notamment la configuration du serveur smtp sortant qui semble devoir se faire à part et donc sur chacun des postes utilisateurs...


----------



## bompi (28 Septembre 2015)

Dans ce cas, il te faut privilégier les commandes disponibles dans le shell et les intégrer à ton Apple Script.


----------



## domi73 (28 Septembre 2015)

bompi a dit:


> Dans ce cas, il te faut privilégier les commandes disponibles dans le shell et les intégrer à ton Apple Script.


Oui mais avec quelle commande ? Est-ce qu'il est possible de passer le courriel (destinataire + objet) et la pièce jointe via CURL sans uploader un fichier txt ?

J'ai vu que cela semble possible avec la commande mailx, mais il n'est pas installé par défaut dans Mac OS X.
http://heirloom.sourceforge.net/mailx.html

Avez-vous d'autres idées ?


----------



## bompi (28 Septembre 2015)

La messagerie, c'est à la fois simple et subtil...

Tu peux parfaitement constituer l'ensemble du message, avec les pièces jointes et tout, puis envoyer tout à la fois.

Pour l'envoi, avec un _telnet_ ça se fait :

```
#!/bin/sh
myHost=smtp.xyz.fr
myPort=25
myFrom=alfred.hitchcock@brol.fr
myTo=cary.grant@brol.fr

( echo open ${myHost} ${myPort}
sleep 1
echo HELO monserveur.xyz.fr
sleep 1
echo MAIL FROM: ${myFrom}
sleep 1
echo RCPT TO: ${myTo}
sleep 1
echo DATA
sleep 1
echo FROM: ${myFrom}
echo REPLY-TO: ${myFrom}
echo TO: ${myTo}
echo SUBJECT: Un message de test
echo Autobi passebant completi
echo .
sleep 1
echo exit ) | telnet
```

ou _expect_ aussi bien :

```
#!/usr/bin/expect -f
#exp_internal 1
set timeout 20
set emailhost [lindex $argv 0]
set emailto [lindex $argv 1]
set emailfrom [lindex $argv 2]
set subject [lindex $argv 3]

spawn telnet $emailhost 25
expect -re "(.*)Postfix(.*)|(.*)ESMTP(.*)" {
send "helo <cundinamarca>\r"
}
expect -re "250(.*)" {
send "mail from: $emailfrom\r"
}
expect -re "250(.*)" {
send "rcpt to: $emailto\r"
}
expect -re "250(.*)" {
send "data\r"
}
expect -re "354(.*)" {
send "Subject: $subject\n\nTest Email.\r\n\r\n.\r"
}
expect -re "250(.*)" {
send "quit\r"
}
```


----------



## domi73 (28 Septembre 2015)

Oula oui je dirais pas forcément simple mais subtil certainement 

J'ai réussi à m'envoyer un message avec la première proposition, c'est déjà un grand pas !! Merci !

- Par contre, comment faire pour envoyer une pièce jointe p.ex ~/Desktop/fichier.pdf ?

- Quel est la sécurité de cette connection ?
En fait je suis surpris que cela fonctionne sans vraiment m'authentifier au serveur smtp juste via le port 25 et mon adresse email. Normalement mon serveur smtp utilise une authentification sur le port 465 --> SSL --> réponse au défi MD5 --> login et mdp
Je n'ai pas trouvé d'option ssh dans telnet.

Merci d'avance pour ces précisions


----------



## bompi (29 Septembre 2015)

a) pour les pièces jointes :
Primo, il faut les convertir en données que tu peux émettre, c'est à dire du code ASCII. C'est là que la commande *base64* est pratique et assez universelle [la plupart des clients de messagerie sont capables de décoder du base64].
Secundo, il faut les intégrer dans ton texte à envoyer (voir c)).

b) Auparavant, une petite explication.
SMTP est un protocole tout simple.
Tu te connectes au serveur. Tu lui dis bonjour (*HELO <...>*). Tu dis qui tu es (*MAIL FROM:*). Tu dis à qui tu envoies (*RCP TO:*).
Ensuite tu envoies les données (de *DATA* à une dernière ligne contenant un unique caractère, le point).
Dans cette partie "données", on peut (c'est conseillé mais ce n'est pas obligatoire) préciser divers champs, sous une forme basique :
*FROM: *ma.pomme@me.com
*TO: *pere.noel@me.com
*SUBJECT: *Brol
Ces champs sont "plutôt standards" et généralement analysés et repris par les clients de messagerie, sans obligation
[c'est un peu la nuance entre le droit coutumier et une constitution écrite...]
Ensuite on laisse une ligne vide, histoire que ça soit propre.
Enfin vient le corps du message. On le finit avec une ligne contenant un simple point et zou! le serveur clôt le message et cherche à l'envoyer et te donne un accusé de réception.

c) Le corps du message.
En général, ce corps devra être en ASCII. Si on veut y mettre des caractères non ASCII, on doit bien spécifier le codage et modifier les caractères, de sorte qu'il puisse être lu par tout client de messagerie bien conçu (les mal-conçus, on n'y peut pas grand-chose).
Par exemple, pour du français, on utilisera les codages ISO8859-1 ou ISO-8859-15 et on s'efforcera de mettre les caractères accentués sous une forme dite "Quoted Printable" (par exemple : le "é" devient "=E9").
Par ailleurs, s'il doit comporter plusieurs parties, il faut l'indiquer aussi, ainsi que le séparateur de ces parties.

Bref. Voici un exemple qui devrait (à peu près ) fonctionner de corps de message :

```
FROM: alfred.hitchcock@universal.com
TO: tippi.hedren@universal.com
SUBJECT: Birds
MIME-Version: 1.0
Content-type: multipart/mixed;
Boundary="0__=AUTOBIPASSEBANTCOMPLETI-20150929"
Content-Disposition: inline

--0__=AUTOBIPASSEBANTCOMPLETI-20150929
Content-type: text/plain; charset=ISO-8859-1
Content-transfer-encoding: quoted-printable

Hello Tippi,

je vous =E9cris en fran=E7ais pour changer un peu. Est-ce qu'un colibri
vous ferait plaisir pour le prochain No=EBl ?

Yours sincerely,
Alfred

--0__=AUTOBIPASSEBANTCOMPLETI-20150929
Content-type: text/plain; charset=ISO-8859-1
Content-Disposition: attachment; filename="brol.log"
Content-transfer-encoding: base64

QSBwaWN0dXJlIHdvdWxkIGJlIG5pY2UsIGhlcmUsIGRvbid0IHlvdSB0aGluayA/CgpBbnl3YXks
IHRoaXMgd291bGQgYmUgdG9vIGJpZyB0byBwb3N0IGluIHRoaXMgdGhyZWFkLi4uCg==

--0__=AUTOBIPASSEBANTCOMPLETI-20150929--

.
```
dans ce corps de message il y a donc une pièce jointe ("brol.log") au format texte.
Pour un PDF, il faudrait donner le "Content-Type" idoine.


----------



## bompi (29 Septembre 2015)

d) quant à la sécurité, c'est plus compliqué. SMTP est *très* laxiste en soi ; il a donc été enrichi de diverses vérifications pour accroître la sécurité des échanges et tenter de contrôler le spam.
Si tu dois passer à du sécurisé (genre SMTP sur SSL) il faudra adapter le tout.
Personnellement, je n'ai jamais eu à m'en soucier : dans ce cas, je passe par une passerelle permissive qui se connecte sur des passerelles qui ne le sont pas. Genre : j'installe un relais de messagerie non sécurisé sur mon poste mais qui se connecte en mode sécurisé sur les véritables passerelles de messagerie à utiliser pour sortir. Ainsi rien ne sort en clair de mon poste mais je ne me casse pas trop la tête avec STARTTLS ou SSL.


----------



## domi73 (29 Septembre 2015)

Bonjour,
Merci pour ces exemples et explications détaillées. Voici un premier essai de ma part infructueux, car le message que je reçois ne comporte pas la pièce jointe mais le code base64

Pour rappel, j'ai besoin de créer un message simple de ce type


```
A: boite@faxbox.se
Objet: 00331234567
Pièce jointe: Courrier.pdf
```
​Voici donc ma tentative:


```
myHost=myhost.address
myPort=25
myFrom=mon@mail.com
myTo=boite@faxbox.se
myFile="$(base64 ~/Desktop/Courrier.pdf)"

( echo open ${myHost} ${myPort}
sleep 1
echo HELO monserveur.xyz.fr
sleep 1
echo MAIL FROM: ${myFrom}
sleep 1
echo RCPT TO: ${myTo}
sleep 1
echo DATA
sleep 1
echo SUBJECT: 00331234567
echo Content-Disposition: inline;
    filename=Courrier.pdf
Content-Type: application/pdf;
    x-unix-mode=0644;
    name="Courrier.pdf"
Content-Transfer-Encoding: base64
echo ${myFile}
echo .
sleep 1
echo exit ) | telnet
```

Qu'est-ce qui est faux ?


----------



## bompi (29 Septembre 2015)

Déjà, je pense qu'il faudrait définir un délimiteur (_boundary_) pour avoir une partie texte (même réduite à fort peu) et une partie pièce jointe.

Ensuite, tout bonnement, à la place de "echo ${myfile}", il faut mettre directement le code obtenu par la transformation en base64 du fichier "courrier.pdf".


----------



## domi73 (30 Septembre 2015)

Bonjour,
Devant la complexité de la tâche, je me suis finalement décidé pour utiliser un script Perl:

http://caspian.dotconf.net/menu/Software/SendEmail/

Avec cela tout fonctionne en une seule ligne de commande et surtout aussi de façon sécurisé (TLS) avec le serveur SMTP. Le seul bémol étant que je dois installer le script sur chaque machine cliente.

Merci en tout cas pour les explications et tentatives.


----------



## bompi (30 Septembre 2015)

Ça me paraît être une bonne idée.

Note que l'on peut insérer un script Perl dans un AppleScript (exemple), mais il y a sans doute un peu trop de boulot pour ton script ou, plus facilement, dans une application Automator (ajout d'une action "Run shell script" et choisir Perl ; voir par exemple dans ce fil, post #7).


----------



## domi73 (30 Septembre 2015)

Ben en fait, entre-temps, je suis parti sur une solution "à la Filemaker" que je suis en train d'implémenter, on verra si cela fonctionne:

- je stocke le script perl dans un champ multimédia (= similaire à un champ de type blob) dans ma solution Filemaker
- à chaque utilisation du script par un utilisateur, j'exporte d'abord le script dans un fichier temporaire
- j'utilise ensuite le script perl via la fonction filemaker "perform AppleScript --> do shell script ./sendEmail..."

Merci encore pour tous les conseils.


----------

