68

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
  • 935
  • 1
  • 11
  • 18
  • Can't you send email thru a local (or near to you) SMTP server? – Basile Starynkevitch Feb 06 '13 at 07:23
  • 7
    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

4 Answers4

126
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.

goetzc
  • 1,774
  • 2
  • 27
  • 32
bambam
  • 1,746
  • 1
  • 14
  • 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
  • 2
    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 – 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 – 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 – 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? – kabibe sadagat May 21 '22 at 14:40
6

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
  • 844
  • 8
  • 7
  • 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
2

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

Rutger Smit
  • 5
  • 1
  • 2
Shakiba Moshiri
  • 16,284
  • 2
  • 23
  • 38
0

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
  • 11
  • 2