En varias ocasiones, he necesitado enviar un e-mail a un compañero de trabajo (o a mí mismo) con información recién extraída de un servidor (por ejemplo un CSV de base de datos o información subida desde la web) y lo que he hecho al final ha sido bajármelo por SSH y una vez en mi ordenador he enviado el archivo donde ha sido necesario. Si eres como yo, que siempre tengo una sesión SSH abierta en mi servidor, ganarás un par de minutos con este script.
El siguiente script envía un correo electrónico utilizando sendmail. sendmail no es difícil, simplemente tenemos que escribir como entrada del correo las cabeceras necesarias y el mensaje, aunque podemos echar unos minutos hasta que se puede enviar correctamente el mensaje.
El problema con las cabeceras viene cuando tenemos que enviar archivos adjuntos, ya que las cabeceras que tenemos que enviar son un poco más complejas, y luego tenemos que codificar el archivo para que encaje en un e-mail y es algo que a mano resulta muy pesado.
Pues nada, si salvamos esto como gemail.sh sólo tenemos que hacer lo siguiente:
$ email.sh destino@servidor.com «Asunto del mensaje» «Hola mundo! Te mando un mensaje»
para enviar un mensaje normal, si queremos enviar adjuntos:
$ email.sh destino@servidor.com «Asunto del mensaje» «Hola mundo! Te mando un mensaje» fichero1 fichero2
siempre y cuando existan los archivos, la cosa irá bien, aunque también podemos insertar cabeceras nuevas en el correo, por ejemplo From (para especificar el remitente), CC y BCC (para copias) y Reply-to (para responder a esta dirección), etc. de la siguiente manera:
$ email.sh destino@servidor.com «Asunto del mensaje» «Hola mundo! Te mando un mensaje» «From: Yo mismo
» «CC: un_amigo@direccion.com» fichero1 fichero2…
Siempre y cuando tengamos sendmail configurado, todos los e-mails se enviarán. Si algún e-mail no ha salido, podemos ver en /var/log/mail.log y /var/log/mail.err qué ha pasado con el envío, ya que sendmail se limita a encolar los mensajes, que ya se podrán enviar con el método que tengamos configurado (postfix, nullailer, etc)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | #!/bin/bash # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # gemail.sh Copyright (C) 2014 Gaspar Fernández <gaspar.fernandez@totaki.com> # This bash script will help you to use sendmail allowing us to send e-mails from # the terminal in a friendly way just say destination, subject and body in the command # arguments. It allows us also to send mail attachments with local files and allows you # to use internal sendmail application or connection to a SMTP server. # # I find it interesting when using remotely a server with SSH and I must send a file # located in it to someone. I wrote this little script to send the file directly to # the destination. # Changelog: # - 20160902: Fixed bad python indentation (after yesterday's re-indentation) # - 20160901: Fix selecting SMTP user # Fix when sending mails through cron jobs (again) this time, # when sending from scripts ran in cron jobs. /dev/stdin is # present in some conditions but with no data. # Indentation fix # - 20160706: Several new CLI options. # - 20160705: Added SMTP support with tiny python script # - 20160703: Fixes adding headers and autoheaders # - 20160415: Fix sending mails through cron job. Must check permissions over /dev/stdin # - 20150216: Allow body to be read from stdin # - 20150210: Bug fix separate recipient and non-recipient headers (for some reason some # mailers didn't do it right when they are mixed. # - 20150210: Added SENDMAIL_BASIC_ARGS to call sendmail -t and allow more recipients # - 20150113: Bug fix (sendmail with no arguments) # - 20141212: Preview mode and additional sendmail find # - 20141211: Removed extra \n when no extra headers # - 20141208: Allows us to send many attachments # - 20141206: Code clean up # - 20141129: Initial idea of the script and wrote basic functionality # To do: # - Doc and examples !!! VERSION="0.8" #MAIL_BOUNDARY="m41lb0und4ry" # We can randomize it later MAIL_BOUNDARY=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 40` SENDMAIL_COMMAND=`which sendmail` # Read recipients from mail (to use CC and so) SENDMAIL_BASIC_ARGS="-t" SENDMAIL_COMMAND=""; SMTP_DEFAULT_SECURITY="starttls" _MYNAME=$0 function showUsage() { # We must extend this help to use headers and so if [ -n "$1" ] then echo "Sorry: $1" echo fi echo "gemail.sh Version $VERSION" echo "Sends e-mails from terminal the easy way. (https://github.com/gasparfm/gscripts)" echo echo "Use:" echo " $_MYNAME [options] [destination] [subject] [body] [attachment1] [attachment2] ... [attachmentN]" echo echo "or:" echo echo " $_MYNAME [options] [destination] [subject] [attachment1] [attachment2] ... [attachmentN] < bodyfile" echo echo "These are the supported options:" echo " -t, --to=destination : Adds to recipient to the e-mail (if this option is" echo " present you can dismiss [destination] argument)." echo " -f, --from=origin : This is YOUR e-mail." echo " -s, --subject=subject : The subject of your message. (if this option is " echo " present you can dismiss [subject] argument)." echo " -b, --body=message : This is yout message. (if this option is present," echo " you can dismiss [body] argument)." echo " -p, --preview : Don't send the message, just preview the e-mail." echo " -h, --header=content : Adds new header to the e-mail. Allowed headers are:" echo " From, CC, BCC, Reply-to, Date, Organization, " echo " X-Mailer and Message-Id." echo " -a, --attach=file : Attaches this file to the e-mail." echo " -e, --smtp=conn_str : Gives SMTP server or connection string." echo " This connection string can be: " echo " * server hostname or IP" echo " * user:password@server (if user or password has :" echo " or @ characters they may be escaped.)" echo " -u, --smtp-user=user : Sets SMTP server user." echo " -w, --smtp-pass=passwd : Sets SMTP server password." echo " -n, --noautoheaders : Disables gemail.sh automatic headers." echo echo "You can also insert some more headers after the attachments:" echo " "From: me@email.ext" or "From: Me <me@myself.ext>" to specify my email" echo " "CC: my@email.ext" or "CC: My friend <my@friend.ext>" for carbon copy" echo " "BCC: my@email.ext" or "BCC: My friend <my@friend.ext>" for blind carbon copy" echo " "Reply-to: another@email.com" for a new reply-to address"; echo " Another headers accepted: Date, Organization, X-Mailer, Message-Id" echo echo "You can use the keyword *preview* to print the command to be executed (if you have attached files the output can be large)" exit } function findSendmail() { # Try to find again sendmail in extra paths not in $PATH EXTRAPATHS=("/usr/sbin/" "/sbin/" "/usr/local/sbin/" "$HOME/.local/bin/") for p in "${EXTRAPATHS[@]}"; do if [ -x "${p}sendmail" ] then echo "${p}sendmail" return fi done } function test_py() { if [ -z "$(which python)" ] then echo "Python not found" return; fi python <<EOF try: import smtplib except ImportError as er: print er EOF } function pysmtp() { TO="$1" while read line do echo "$line" done | python <(cat <<EOF import smtplib import sys try: smtpObj = smtplib.SMTP('$SMTP_SERVER') if ('$SMTP_SECURITY' == 'starttls'): smtpObj.starttls() if ('$SMTP_USER'): smtpObj.login('$SMTP_USER', '$SMTP_PASS') message = sys.stdin.read() _from = message.find('From:') fromstr = 'root' if _from != -1: fromstr = message[_from+5:message.find('\n', _from)] smtpObj.sendmail(fromstr.strip(), '$_TO', message) except Exception as e: print e EOF ) } function callsend() { _TO="$1" _PREVIEW=$2 if (( $_PREVIEW==1 )) then cat elif [ $SENDER = "sendmail" ] then if [ -z "$SENDMAIL_COMMAND" ]; then echo "No sendmail found in your PATH. Make sure you have it!" exit 1; fi $SENDMAIL_COMMAND $SENDMAIL_BASIC_ARGS "$_TO" elif [ $SENDER = "smtp" ] then PYERR="$(test_py)" if [ -n "$PYERR" ] then echo "Python error: $PYERR" exit 1; fi RESPONSE="$(pysmtp "$TO")" if [ -n "$RESPONSE" ] then echo "Error sending via SMTP: $RESPONSE" return 1; fi fi } function add_attachment() { ATTACH="$1" ATTACH_MIME=`file --mime-type -b "$ATTACH"` ATTACH_NAME=`basename "$ATTACH"` ATTACH_BASE64=`base64 "$ATTACH"` ATTACHMENTS="$ATTACHMENTS --$MAIL_BOUNDARY Content-Type: $ATTACH_MIME; name="$ATTACH_NAME" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="$ATTACH_NAME" $ATTACH_BASE64" } function add_header() { HEADERINFO="$1" OLDIFS=$IFS IFS=":" read -a HEADER <<< "$HEADERINFO" IFS=$OLDIFS case ${HEADER[0]} in # Separating headers for some mail systems "From" | "Reply-to" | "CC" | "BCC" ) if [ "${HEADER[0]}" = "From" ] || [ "${HEADER[0]}" = "Reply-to" ] then RECIPIENTS="$(echo -e "$RECIPIENTS" | grep -v "${HEADER[0]}:")" fi if [ -z "$RECIPIENTS" ] then RECIPIENTS=$HEADERINFO else RECIPIENTS="`echo -e "$RECIPIENTS""\n""$HEADERINFO"`" fi ;; "Date" | "X-Mailer" | "Organization" | "Message-Id" ) MOREHEADERS="$(echo -e "$MOREHEADERS" | grep -v "${HEADER[0]}:")" if [ -z "$MOREHEADERS" ] then MOREHEADERS=$HEADERINFO else MOREHEADERS="`echo -e "$MOREHEADERS""\n""$HEADERINFO"`" fi ;; "preview") PREVIEW=1 ;; *) showUsage "Attachment $HEADERINFO not found" esac } function add_auto_headers() { if [ "$AUTOHEADERS" = "yes" ] then if [ -z "$(grep "From:" <<< $RECIPIENTS)" ] then add_header "From: $(echo `whoami`@`hostname`)" fi if [ -z "$(grep "Date: " <<< $MOREHEADERS)" ] then add_header "Date: $(date -R) ($(date +%Z))" fi if [ -z "$(grep "Message-Id: " <<< $MOREHEADERS)" ] then _FROM=$(grep "From:" <<< $RECIPIENTS) add_header "Message-Id: <"$(uuidgen | awk -F'-' -v date=$(date +%Y%m%d%H%M%S) -v at=$(echo $_FROM | cut -d'@' -f2) '{print $1$2"."date"."$3$4"@"at}')">" fi if [ -z "$(grep "X-Mailer: " <<< $MOREHEADERS)" ] then add_header "X-Mailer: gemail.sh Ver. $VERSION" fi fi } function smtp_settings() { STS="$1" OLDIFS=$IFS IFS=$(echo -e "\n") while read user do read pass read server break done <<< $(sed -r 's/([^\:\@]*(\\:[^\:\@]*)*):([^\@]*(\\@[^\:\@]*)*)@([^\/\:]*)/\1\n\3\n\5/' <<< "$STS"); if [ -z "$user" ] then showUsage "Wrong SMTP server string: "$STS"" fi SENDER="smtp" if [ -z "$pass" ] && [ -z "$server" ] then # We only have server SMTP_SERVER="$user" else SMTP_SERVER="$server" SMTP_USER="$user" SMTP_PASS="$pass" fi SMTP_SECURITY=$SMTP_DEFAULT_SECURITY } # Fill missing headers automatically AUTOHEADERS="yes" ATTACHMENTS="" MOREHEADERS="" RECIPIENTS="" # By default, no PREVIEW PREVIEW=0 # By default, sent by sendmail SENDER="sendmail" # Parse input arguments ARGS=$(getopt -q -o "t:f:s:b:ph:a:e:u:w:n" -l "to:,from:,subject:,body:,preview,header:,attach:,smtp:,smtp-user:,smtp-pass:,noautoheaders" -n "gemail.sh" -- "$@"); if [ $? -ne 0 ]; then showUsage "Error parsing arguments" fi eval set -- "$ARGS"; while [ $# -gt 0 ]; do case "$1" in -t|--to) TO="$2" shift; ;; -f|--from) add_header "From: $2" shift; ;; -s|--subject) SUBJECT="$2" shift; ;; -b|--body) BODY="$3" shift; ;; -p|--preview) PREVIEW=1 ;; -h|--header) add_header "$2" shift; ;; -a|--attach) add_attachment "$2" shift; ;; -e|--smtp) smtp_settings "$2" shift; ;; -u|--smtp-user) SMTP_USER="$2" shift ;; -w|--smtp-pass) SMTP_PASS="$2" shift ;; -n|--noautoheaders) AUTOHEADERS="no" ;; --) shift; break; ;; *) echo "Unrecognised option "$1"" showUsage esac shift; done if [ -n "$1" ] && [ -z "$TO" ] then TO="$1" shift fi if [ -n "$1" ] && [ -z "$SUBJECT" ] then SUBJECT="$1" shift fi # If we have data in /dev/stdin pick up the email body from /dev/stdin # -t 0 : make sure stdin (fd=0) is not a terminal as this program is not # interactive if [ -r /dev/stdin ] && [ ! -t 0 ] then BODY=$(cat /dev/stdin) fi # If we have no body yet, test the argument. In cron jobs /dev/stdin may # be detected with no data. if [ -n "$1" ] && [ -z "$BODY" ] then BODY="$1" shift fi # Additional sendmail find if not in PATH if [ -z "$SENDMAIL_COMMAND" ]; then SENDMAIL_COMMAND=`findSendmail` fi # Fill attachments and additional user headers while [ $# -gt 0 ] do ATTACH="$1" if [ ! -r "$ATTACH" ]; then # Not an attachment, ok but it can be an additional header it will have : let's check it add_header "$ATTACH" else add_attachment "$ATTACH" fi shift done if [ -z "$TO" ] then showUsage "No recipient found." elif [ -z "$SUBJECT" ] then showUsage "No subject found." elif [ -z "$BODY" ] then showUsage "No body found." fi # echo "TO: $TO" # echo "SUBJECT: $SUBJECT" # echo "BODY: $BODY" add_auto_headers # Send message ( echo "To: $TO"; if [ -n "$RECIPIENTS" ]; then echo -e "$RECIPIENTS" fi echo "Subject: $SUBJECT"; if [ -n "$MOREHEADERS" ]; then echo -e "$MOREHEADERS" fi echo "MIME-Version: 1.0"; echo "Content-Type: multipart/mixed; boundary="$MAIL_BOUNDARY""; echo -e "\n" echo "--"$MAIL_BOUNDARY; echo "Content-Type: text/plain"; echo -e "Content-Disposition: inline\n"; echo "$BODY"; echo -e "$ATTACHMENTS" echo "--"$MAIL_BOUNDARY"--") | callsend $TO $PREVIEW RESULT=$? if (( $RESULT==0 )) then echo "Message sent successfully"; else echo "Could not send message" fi |
Este código lo encontráis también en mi Github.
Actualización 05/11/2016 : Se ha actualizado el código fuente, para copiar y pegar directamente. Estoy preparando también un post con ejemplos de uso muy ilustrativo que nos puede salvar la vida en más de una ocasión.
Foto: Esparta Palma (Flickr CC-by)
Pingback: Cómo crear milters en Python y configurar Postfix para filtrar correo – Poesía Binaria /
May possibly fairly recently up and running an important web log, the data one offer you on this web site contains given a hand to all of us substantially. Bless you designed for your current precious time & get the job done. UFABETแทงบอลบนมือถือที่ดีที่สุด
I assumed it is usually a preview to post in case others appeared to be having problems getting acquainted with nonetheless We’re a little bit hesitant merely i’m permitted to decide to put companies plus covers for listed here. UFABETราคาต่อรองบอลดีที่สุดในเอเชีย