76

How can I use the curl command line program to send an email from a gmail account?

I have tried the following:

curl -n --ssl-reqd --mail-from "<sender@gmail.com>" --mail-rcpt "<receiver@server.tld>" --url smtps://smtp.gmail.com:465 -T file.txt

With file.txt being the email's contents, however, when I run this command I get the following error:

curl: (67) Access denied: 530

Is it possible to send an email from an account that is hosted by a personal server, still using curl? Does that make the authentication process easier?

NSNolan
  • 1,025
  • 1
  • 13
  • 18
  • Can't you send email thru a local (or near to you) SMTP server? – Basile Starynkevitch Feb 06 '13 at 07:23
  • 9
    Indeed I could, but that was not the question. – NSNolan Feb 06 '13 at 07:27
  • It does not surprise me that Google forbids using their SMTP server as spam proxies... – Basile Starynkevitch Feb 06 '13 at 07:29
  • I think it is possible I just don't think I have my syntax correct. I have attempted slight variations of what I posted and have gotten different feedback such as prompting me for a password, but the email still fails... – NSNolan Feb 06 '13 at 07:33
  • I believe Gmail will require you to use Oauth for authentication. This won't be easy with curl. You can see Google's Oauth documentation at https://developers.google.com/google-apps/gmail/xoauth2_protocol . – rojo Feb 06 '13 at 14:52

5 Answers5

136
curl --ssl-reqd \
  --url 'smtps://smtp.gmail.com:465' \
  --user 'username@gmail.com:password' \
  --mail-from 'username@gmail.com' \
  --mail-rcpt 'john@example.com' \
  --upload-file mail.txt

mail.txt file contents:

From: "User Name" <username@gmail.com>
To: "John Smith" <john@example.com>
Subject: This is a test

Hi John,
I’m sending this mail with curl thru my gmail account.
Bye!

Additional info:

  1. I’m using curl version 7.21.6 with SSL support.

  2. You don't need to use the --insecure switch, which prevents curl from performing SSL connection verification. See this online resource for further details.

  3. It’s considered a bad security practice to pass account credentials thru command line arguments. Use --netrc-file. See the documentation.

  4. You must turn on access for less secure apps or the newer App passwords.

goetz
  • 2,018
  • 2
  • 30
  • 33
bambam
  • 1,886
  • 1
  • 15
  • 9
  • 2
    Thanks man. That totally did the trick. Any recommendations for doing this more securely. I want to have a cron job on my server run a script that will send out emails at a specific time. I figured a curl command would be the easiest but not the most secure. I am not very familiar with smtp servers and such, so any advice would be much appreciated. – NSNolan Apr 18 '13 at 19:31
  • 1
    If I'd want to use something like that to send automated mails from a bash script while avoiding password in the command line ? I've noticed that if you omit the password part you get prompted so I could use expect to deal with that but is there a simpler approach to have curl read from a redirect ? or maybe even an environment variable ? – louigi600 Oct 05 '16 at 08:13
  • 3
    oh ... I get it ... yo can put credentials in .netrc – louigi600 Oct 05 '16 at 08:51
  • 1
    The command is successfully executed but the email arrives empty, no content. – 3bdalla Mar 08 '17 at 11:10
  • 4
    @louigi600, I wouldn't use a .netrc file. However, you could use the `--netrc-file` parameter, and then use bash subshell redirection. E.g. `curl --netrc-file <(printf '%s' "${MY_CREDENTIALS}"` ... `bash` will create a file descriptor to feed the credential data in, and (I think) the data won't even touch disk. – Michael Mol May 30 '19 at 16:34
  • @MichaelMol Could you please provide the whole command, at least the part where `--netrc-file` should be printed? Is it like: `curl --user --netrc-file <(printf '%s' "${MY_CREDENTIALS}"` ? – khashashin Jan 03 '22 at 00:06
  • @khashashin, SO won't let me edit my comment, but I see I had a syntax error. Try something like `--netrc-file <(printf '%s' "${MY_CREDENTIALS}")` somewhere in your command. (My original comment was missing a closing paren. – Michael Mol Jan 04 '22 at 02:00
  • How about multiple recipients? – Steve Moretz Apr 08 '22 at 05:54
  • what if I want to send the message directly from the command line, not from a file? – 0xdeadbeef May 21 '22 at 14:40
  • How to attach a file to the email ? – cwhisperer Aug 09 '22 at 07:52
9

if one wants to send mails as carbon copy or blind carbon copy:

curl --url 'smtps://smtp.gmail.com:465' --ssl-reqd \
  --mail-from 'username@gmail.com' --mail-rcpt 'john@example.com' \
  --mail-rcpt 'mary@gmail.com' --mail-rcpt 'eli@example.com' \
  --upload-file mail.txt --user 'username@gmail.com:password' --insecure
From: "User Name" <username@gmail.com>
To: "John Smith" <john@example.com>
Cc: "Mary Smith" <mary@example.com>
Subject: This is a test

a BCC recipient eli is not specified in the data, just in the RCPT list.

soloturn
  • 958
  • 9
  • 8
  • 1
    No, that's incorrect, or at least dubious; there is no need for the email message to contain an explicit Bcc: header. As far as SMTP is concerned, the message headers are just data, and the *actual* recipients are specified by other means (in this case, by specifying `--mail-rcpt` multiple times if you want to send to multiple recipients). – tripleee Jan 02 '20 at 09:09
  • 1
    yes. it was incorrect thanks for pointing out! i am correcting the answer. see also here: https://stackoverflow.com/questions/2750211/sending-bcc-emails-using-a-smtp-server. – soloturn Jan 02 '20 at 09:34
3

Crate a simple email.conf file like so

Username:   hi@example.com
Password:   OKbNGRcjiV
POP/IMAP Server:    mail.example.com

And simply run sendmail.sh, like so after making it executable (sudo chmod +x sendmail.sh)

./sendmail.sh

Code

#!/bin/bash

ARGS=$(xargs echo  $(perl -anle 's/^[^:]+//g && s/:\s+//g && print' email.conf) < /dev/null)
set -- $ARGS "$@";  

declare -A email;
email['user']=$1
email['pass']=$2
email['smtp']=$3
email['port']='587';
email['rcpt']='your-email-address@gmail.com';


email_content='From: "The title" <'"${email['user']}"'>
To: "Gmail" <'"${email['rcpt']}"'>
Subject: from '"${email['user']}"' to Gmail
Date: '"$(date)"'

Hi Gmail,
'"${email['user']}"' is sending email to you and it should work.
Regards
';


echo "$email_content" | curl -s \
    --url "smtp://${email['smtp']}:${email['port']}" \
    --user "${email['user']}:${email['pass']}" \
    --mail-from "${email['user']}" \
    --mail-rcpt "${email['rcpt']}" \
    --upload-file - # email.txt


if [[ $? == 0 ]]; then
    echo;
    echo 'okay';
else
    echo "curl error code $?";
    man curl | grep "^ \+$? \+"
fi

more

RuSm
  • 27
  • 1
  • 5
Shakiba Moshiri
  • 21,040
  • 2
  • 34
  • 44
1

Mind that the form of mail.txt seems to be important / CRLF for win, LF for Linux, special characters etc.

Finally after struggling 2 hours, it works for me for GMX (they tell their SMPT port to be 587 - and further down in small letters the hint: "also 465 can be used with SSL"):

UNDER Linux (TinyCore Linux on Raspberry 3B+ with curl.tcz installed):

curl --ssl-reqd --url 'smtps://mail.gmx.net:465' --user 'mymail@gmx.at:mymailPassword' --mail-from 'mymail@gmx.at' --mail-rcpt 'mymail@gmx.at' --upload-file mail.txt

UNDER Windows:

curl --ssl-reqd --url "smtps://mail.gmx.net:465" --user "mymail@gmx.at:mymailPassword" --mail-from "mymail@gmx.at" --mail-rcpt "mymail@gmx.at" --upload-file mail_win.txt

with mail.txt:

From: "User Name" <mymail@gmx.at>
To: "John Smith" <mymail@gmx.at>
Subject: This is a test

Hi John,
Im sending this mail with curl thru my gmx account.
Bye!
El Gigante
  • 21
  • 3
0

Note that if Perl's "system()" function is used to execute the curl command, each argument 'word' is a separate item in the argument array, and words must NOT be quoted.

Also note that if sending via Gmail after May 30, 2022, the gmail account must be set up with 2-factor authentication and then you must create an "App Password". The App Password is a long character string that acts as an alternative password and replaces the usual password on the "--user" parameter.

IAM_AL_X
  • 1,221
  • 11
  • 12