web-dev-qa-db-fra.com

Envoi de courrier à partir d'un script Bash Shell

J'écris un Bash Script Shell pour Mac qui envoie une notification par e-mail en ouvrant une application d'automatisme qui envoie des e-mails avec le compte de messagerie par défaut dans Mail.app. L'application d'automatisation joint également un fichier texte sur lequel le script a écrit. Les problèmes avec cette solution sont

  1. Il est visible dans l'interface graphique lors de l'envoi
  2. Il vole le focus si Mail n'est pas l'application actuelle
  3. Cela dépend de la configuration du compte Mail.app en cours de validité à l'avenir

Je pense que pour contourner ces lacunes, je devrais envoyer le courrier directement à partir du script en entrant SMTP paramètres, adresse à envoyer, etc. directement dans le script. Le hic, c'est que je voudrais déployer ce script sur plusieurs ordinateurs (10.5 et 10.6) sans activer Postfix sur l'ordinateur. Est-il possible de le faire dans le script afin qu'il s'exécute sur une installation de base de Mac OS X de 10,5. et 10,6?

Mise à jour: j'ai trouvé le -bs option pour Sendmail qui semble être ce dont j'ai besoin, mais je ne sais pas comment spécifier les paramètres.

De plus, pour clarifier, la raison pour laquelle je voudrais spécifier les paramètres SMTP est que les e-mails de l'hôte local sur le port 25 envoyés via Postfix seraient bloqués par la plupart des pare-feu d'entreprise, mais si je spécifie le serveur et un port alternatif, je ne fonctionnerai pas dans ce problème.

35
ridogi

Étant donné que Mac OS X inclut Python, envisagez d'utiliser un script Python au lieu d'un script Bash. Je n'ai pas testé la partie d'envoi, mais elle suit le exemple standard .

Script Python

# Settings

SMTP_SERVER = 'mail.myisp.com'
SMTP_PORT = 25
SMTP_USERNAME = 'myusername'
SMTP_PASSWORD = '$uper$ecret'
SMTP_FROM = '[email protected]'
SMTP_TO = '[email protected]'

TEXT_FILENAME = '/script/output/my_attachment.txt'
MESSAGE = """This is the message
to be sent to the client.
"""

# Now construct the message
import smtplib, email
from email import encoders
import os

msg = email.MIMEMultipart.MIMEMultipart()
body = email.MIMEText.MIMEText(MESSAGE)
attachment = email.MIMEBase.MIMEBase('text', 'plain')
attachment.set_payload(open(TEXT_FILENAME).read())
attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(TEXT_FILENAME))
encoders.encode_base64(attachment)
msg.attach(body)
msg.attach(attachment)
msg.add_header('From', SMTP_FROM)
msg.add_header('To', SMTP_TO)

# Now send the message
mailer = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
# EDIT: mailer is already connected
# mailer.connect()
mailer.login(SMTP_USERNAME, SMTP_PASSWORD)
mailer.sendmail(SMTP_FROM, [SMTP_TO], msg.as_string())
mailer.close()

J'espère que ça aide.

53
Jason R. Coombs

En fait, le "courrier" fonctionne aussi bien.

mail -s "subject line" [email protected] < filename

fonctionne parfaitement, tant que SMTP est configuré sur votre machine. Je pense que la plupart des Mac le font, par défaut.

Si vous ne disposez pas de SMTP, la seule chose que vous pourrez faire est de passer par Mail.app. Une manière ALTERNATIVE de passer par mail.app est via AppleScript . Lorsque vous dites à Mail.app d'envoyer du courrier via AppleScript, vous pouvez lui dire de ne pas faire apparaître de fenêtre ... (cela nécessite toujours la configuration de Mail.app).

Introduction to Scripting Mail a une bonne description de la façon de travailler avec le courrier dans AppleScript.

38
Brian Postow

Il existe un programme appelé Sendmail .

Vous ne voulez probablement pas utiliser le -bs à moins que vous ne l'envoyiez en SMTP brut comme l'exemple de Martin. -bs sert à exécuter un serveur SMTP en tant que démon. Sendmail enverra directement au serveur de messagerie récepteur (sur le port 25), sauf si vous le remplacez dans le fichier de configuration. Vous pouvez spécifier le fichier de configuration par le -C paramètre.

Dans la configuration, vous pouvez spécifier un serveur relais (tout serveur de messagerie ou sendmail exécutant -bs sur une autre machine)

L'utilisation d'un serveur de relais correctement configuré est une bonne idée car lorsque le service informatique gère des serveurs de messagerie, il implémente SPF et clés de domaine . Cela garde votre courrier hors de la poubelle.

Si le port 25 est bloqué, vous avez deux options.

  1. Utilisez le serveur SMTP d'entreprise.
  2. Courir sendmail -bd sur une machine en dehors du pare-feu d'entreprise qui écoute sur un port autre que 25.

Je pense que vous pouvez ajouter des paramètres de configuration sur la ligne de commande. Ce que vous voulez, c'est l'option SMART_Host. Appelez donc Sendmail comme sendmail -OSMART_Host=nameofhost.com.

15
Byron Whitlock

La seule façon de le faire, tout en conservant le programme autosuffisant, est probablement si vous avez un accès direct à un serveur SMTP à partir des clients.

Si vous avez un accès direct à un serveur SMTP, vous pouvez utiliser exemple SMTP de wikipedia et le transformer en quelque chose comme ceci:

#!/bin/bash
telnet smtp.example.org 25 <<_EOF
HELO relay.example.org
MAIL FROM:<[email protected]>
RCPT TO:<[email protected]>
DATA
From: Joe <[email protected]>
To: Jane <[email protected]>
Subject: Hello

Hello, world!
.
QUIT
_EOF

Pour gérer les erreurs, je redirigerais la sortie de telnet vers un fichier, puis je le grepais pour un "message de réussite" plus tard. Je ne suis pas sûr du format du message, mais je vois quelque chose comme "250 2.0.0 Ok: mis en file d'attente en tant que D86A226C574" dans la sortie de mon serveur SMTP. Cela me ferait grpper pour "^ 250. * en file d'attente comme".

10
Martin Olsen

sendEmail est un script que vous pouvez utiliser pour envoyer des e-mails à partir de la ligne de commande en utilisant des paramètres plus compliqués, y compris la connexion à un serveur smtp distant: http://caspian.dotconf.net/menu/Software/SendEmail/ =

Sur OSX, il est facilement installable via macports: http://sendemail.darwinports.com/

Ci-dessous la page d'aide de la commande, notez les drapeaux -s, -xu, -xp:

Synopsis:  sendEmail -f ADDRESS [options]

Required:
  -f ADDRESS                from (sender) email address
  * At least one recipient required via -t, -cc, or -bcc
  * Message body required via -m, STDIN, or -o message-file=FILE

Common:
  -t ADDRESS [ADDR ...]     to email address(es)
  -u SUBJECT                message subject
  -m MESSAGE                message body
  -s SERVER[:PORT]          smtp mail relay, default is localhost:25

Optional:
  -a   FILE [FILE ...]      file attachment(s)
  -cc  ADDRESS [ADDR ...]   cc  email address(es)
  -bcc ADDRESS [ADDR ...]   bcc email address(es)

Paranormal:
  -xu USERNAME              authentication user (for SMTP authentication)
  -xp PASSWORD              authentication password (for SMTP authentication)
  -l  LOGFILE               log to the specified file
  -v                        verbosity, use multiple times for greater effect
  -q                        be quiet (no stdout output)
  -o NAME=VALUE             see extended help topic "misc" for details

Help:
  --help TOPIC              The following extended help topics are available:
      addressing            explain addressing and related options
      message               explain message body input and related options
      misc                  explain -xu, -xp, and others
      networking            explain -s, etc
      output                explain logging and other output options
6
Mark Carey

Envoyez du courrier de Bash avec une seule ligne:

echo "your mail body" | mail -s "your subject" [email protected] -a "From: [email protected]"
5
Olivier

Voici un simple script Ruby pour ce faire. Ruby est livré avec les versions de Mac OS X que vous avez mentionnées.

Remplacez tous les bits marqués "remplacer". S'il échoue, il renvoie un code de sortie différent de zéro et une trace arrière Ruby.

require 'net/smtp'

SMTPHOST = 'replace.yoursmtpserver.example.com'
FROM = '"Your Email" <[email protected]>'

def send(to, subject, message)
  body = <<EOF
From: #{FROM}
To: #{to}
Subject: #{subject}

#{message}
EOF
  Net::SMTP.start(SMTPHOST) do |smtp|
    smtp.send_message body, FROM, to
  end
end

send('[email protected]', 'testing', 'This is a message!')

Vous pouvez intégrer cela dans un script Bash comme ceci:

Ruby << EOF
 ... script here ...
EOF

Pour d'autres façons d'envoyer des courriels Ruby, voir la question Stack Overflow Comment envoyer du courrier à partir d'un programme Ruby?.

Vous pouvez également utiliser d'autres langues fournies avec Mac OS X:

4
docwhat

Je l'ai préparé pour le défi. Si vous supprimez l'appel à "Dig" pour obtenir le relais de messagerie, il s'agit d'un script Bash 100% natif.

#!/bin/bash
MAIL_FROM="[email protected]"
RCPT_TO="[email protected]"
MESSAGE=message.txt
SMTP_PORT=25
SMTP_DOMAIN=${RCPT_TO##*@}

index=1
while read PRIORITY RELAY
do
    RELAY[$index]=$RELAY
    ((index++))
done < <( Dig +short MX $SMTP_DOMAIN )

RELAY_COUNT=${#RELAY[@]}
SMTP_COMMANDS=( "HELO $HOSTNAME" "MAIL FROM: <$MAIL_FROM>" "RCPT TO: <$RCPT_TO>" "DATA" "." "QUIT" )
SMTP_REPLY=([25]=OK [50]=FAIL [51]=FAIL [52]=FAIL [53]=FAIL [54]=FAIL [55]=FAIL [45]=WAIT [35]=DATA [22]=SENT)

for (( i = 1 ; i < RELAY_COUNT ; i++ ))
do
    SMTP_Host="${RELAY[$i]}"
    echo "Trying relay [$i]: $SMTP_Host..."
    exec 5<>/dev/tcp/$SMTP_Host/$SMTP_PORT
    read HELO <&5
    echo GOT: $HELO
    for COMMAND_ORDER in 0 1 2 3 4 5 6 7
    do
            OUT=${SMTP_COMMANDS[COMMAND_ORDER]}
            echo SENDING: $OUT
            echo -e "$OUT\r" >&5

            read -r REPLY <&5
            echo REPLY: $REPLY
            # CODE=($REPLY)
            CODE=${REPLY:0:2}
            ACTION=${SMTP_REPLY[CODE]}
            case $ACTION in
                    WAIT )          echo Temporarily Fail
                                                    break
                                                    ;;
                    FAIL )          echo Failed
                                                    break
                                                    ;;
                    OK )                            ;;
                    SENT )          exit 0
                                                    ;;
                    DATA )          echo Sending Message: $MESSAGE
                                                    cat $MESSAGE >&5
                                                    echo -e "\r" >&5
                                                    ;;
                    * )         echo Unknown SMTP code $CODE
                                                    exit 2
            esac
    done
done
4
Orwellophile

sendmail et même postfix peuvent être trop gros à installer si tout ce que vous voulez faire est d'envoyer quelques e-mails à partir de vos scripts.

Si vous avez un compte Gmail par exemple, vous pouvez utiliser les serveurs de Google pour envoyer des e-mails en utilisant SMTP . Si vous ne souhaitez pas utiliser le serveur de gGoogle, tant que vous avez accès à un serveur SMTP, cela devrait fonctionner.

Un programme très léger qui le rend facile à faire est msmtp . Ils ont exemples de fichiers de configuration dans leur documentation .

La façon la plus simple de le faire serait de configurer une valeur par défaut à l'échelle du système:

account default
Host smtp.gmail.com
from [email protected]
user [email protected]
password XXX
port 587

msmtp devrait être très facile à installer. En fait, il y a n port pour cela, donc ça pourrait être aussi simple que port install msmtp.

Après avoir installé et configuré msmtp, vous pouvez envoyer un e-mail à [email protected] en utilisant:

mail -s <subject> [email protected] <<EOF
<mail text, as many lines as you want. Shell variables will be expanded>.
EOF

Vous pouvez mettre ce qui précède dans un script. Voir man mail pour plus de détails.

3
Alok Singhal

1) Pourquoi ne pas configurer postfix pour gérer uniquement le courrier sortant et le relayer via une passerelle de messagerie? Son plus grand avantage est qu'il est déjà installé sur les clients OS X.

2) Installez et configurez l'un des MTA légers qui ne gèrent que le courrier sortant, comme nullmailer ou ssmtp (disponible via MacPorts).

Dans les deux cas, utilisez mailx(1) (ou mutt si vous voulez faire preuve de fantaisie) pour envoyer les e-mails à partir d'un script Shell.

Il y a plusieurs questions sur la défaillance du serveur qui entrent dans les détails.

3
user3850

Voici un extrait de script shells modifié que j'ai utilisé sur divers systèmes UNIX ... (echo "${MESSAGE}" | ${uuencode} ${ATTACHMENT} $ basename $ {ATTACHMENT} ) | ${mailx} -s "${SUBJECT}" "${TO_LIST}"

uuencode et mailx sont définis sur les exécutables. Les autres variables proviennent d'une entrée utilisateur analysée à l'aide de getopts.

Cela fonctionne, mais je dois admettre le plus souvent que j'utilise un simple programme Java pour envoyer des e-mails sur la console).

0
tmeisenh

Essayez mtcmail. C'est un expéditeur d'e-mails assez complet, complètement autonome.

0
motobói