Using Curl to Send Email

Using curl to send email

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.

How to send plain text emails using cURL

If you use the -T (--upload-file) option, curl will not issue a VRFY command.

See https://ec.haxx.se/usingcurl-smtp.html

Example:

curl smtp://mail.example.com --mail-from myself@example.com \
--mail-rcpt receiver@example.com \
--upload-file email.txt

When curl has a message to send, it will not VRFY and instead do MAIL FROM...RCPT TO.

From man curl:

--mail-rcpt
(SMTP) Specify a single address, user name or mailing list name.

When performing a mail transfer, the recipient should specify a valid email address to send the mail to. (Added in 7.20.0)

When performing an address verification (VRFY command), the recipient should be specified as the user name or user name and
domain (as
per Section 3.5 of RFC5321). (Added in 7.34.0)

It's not very well stated, but if the command is lacking a message (-T or --upload-file), then curl performs address verification.

can curl no longer send emails using gmail accounts?

Don't know if will solve your problem, but if you have enabled 2-Step Verification in your Google account, you have to create some app password

Sending an email using curl c++

I found this to be a helpful starting point:
https://curl.se/libcurl/c/smtp-mail.html

There are two main problems with your code:

  1. Your read_function didn't keep track of how much of the payload has been read so it would keep giving the same content to libcurl over and over and never signal the end of the message.
  2. You were setting CURLOPT_MAIL_RCPT to a string when in fact it should be a struct curl_slist * because there can be multiple recipients.

Here is a fixed example that I tested on my computer and it worked. Private data at the top of the file was modified before posting.

#define USERNAME "david"
#define PASSWORD "xxxxx"
#define MAILTO "david@example.com"
#define MAILFROM "you@example.com"
#define SMTP "smtp://your.smtp.server.example.com:25"

#include <stdio.h>
#include <curl/curl.h>

const char * payload_text =
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n"
"To: " MAILTO "\r\n"
"From: " MAILFROM "\r\n"
"Subject: SMTP example message with libcurl 6\r\n"
"\r\n"
"Hello world!\r\n";

struct ReadData
{
explicit ReadData(const char * str)
{
source = str;
size = strlen(str);
}

const char * source;
size_t size;
};

size_t read_function(char * buffer, size_t size, size_t nitems, ReadData * data)
{
size_t len = size * nitems;
if (len > data->size) { len = data->size; }
memcpy(buffer, data->source, len);
data->source += len;
data->size -= len;
return len;
}

int main()
{
CURL * curl = curl_easy_init();
if (!curl)
{
fprintf(stderr, "curl_easy_init failed\n");
return 1;
}

curl_easy_setopt(curl, CURLOPT_USERNAME, USERNAME);
curl_easy_setopt(curl, CURLOPT_PASSWORD, PASSWORD);
curl_easy_setopt(curl, CURLOPT_URL, SMTP);
curl_easy_setopt(curl, CURLOPT_MAIL_FROM, MAILFROM);

struct curl_slist * rcpt = NULL;
rcpt = curl_slist_append(rcpt, MAILTO);
curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, rcpt);

ReadData data(payload_text);
curl_easy_setopt(curl, CURLOPT_READDATA, &data);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_function);

curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);

// If your server doesn't have a proper SSL certificate:
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);

CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(curl);
}
return 0;
}

curl : send html email with embedded image and attachment

The solution I came up with is to base64 encode all the attachment (image and text file) and to include them into the uploaded file directly in the multipart/mixed body such as :

--MULTIPART-MIXED-BOUNDARY
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-Disposition: inline
Content-Id: <admin.png>
iVBORw0KGgoAAAANSUhEUgAAAIAAAACgCAIAAABL8POqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA
B3RJTUUH4AQNDwEVouBdqAAAG2xJREFUeNrtfX9oHFe25jdDBU5BG25BG7pABhXEkDJjSIsYIs1m
WbfJA8ubhcjjgdiTQNJOYCInj0RKYGIl8CbyPF4iZSCxEkgsB5LIgWQlL2Pcfow3bdgw0mMzox6e
....


--MULTIPART-MIXED-BOUNDARY
Content-Type: text/plain
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename=log.txt
c29tZSBsb2cgaW4gYSB0eHQgZmlsZSB0byBhdHRhY2ggdG8gdGhlIG1haWwK


--MULTIPART-MIXED-BOUNDARY--

The Content-Id header is used to identify the resource that can be referenced in the html with : cid: like :

<img src="cid:admin.png" width="150" height="50">

Here is a complete bash example to send an html email with and admin.png embedded image and a log.txt attached to it :

#!/bin/bash

rtmp_url="smtp://smtp.gmail.com:587"
rtmp_from="sender@gmail.com"
rtmp_to="receiver@gmail.com"
rtmp_credentials="sender@gmail.com:secretpassword"

file_upload="data.txt"

# html message to send
echo "<html>
<body>
<div>
<p>Hello, </p>
<p>Please see the log file attached</p>
<p>Admin Team</p>
<img src=\"cid:admin.png\" width=\"150\" height=\"50\">
</div>
</body>
</html>" > message.html

# log.txt file to attached to the mail
echo "some log in a txt file to attach to the mail" > log.txt

mail_from="Some Name <$rtmp_from>"
mail_to="Some Name <$rtmp_to>"
mail_subject="example of mail"
mail_reply_to="Some Name <$rtmp_from>"
mail_cc=""

# add an image to data.txt :
# $1 : type (ex : image/png)
# $2 : image content id filename (match the cid:filename.png in html document)
# $3 : image content base64 encoded
# $4 : filename for the attached file if content id filename empty
function add_file {
echo "--MULTIPART-MIXED-BOUNDARY
Content-Type: $1
Content-Transfer-Encoding: base64" >> "$file_upload"

if [ ! -z "$2" ]; then
echo "Content-Disposition: inline
Content-Id: <$2>" >> "$file_upload"
else
echo "Content-Disposition: attachment; filename=$4" >> "$file_upload"
fi
echo "$3

" >> "$file_upload"
}

message_base64=$(cat message.html | base64)

echo "From: $mail_from
To: $mail_to
Subject: $mail_subject
Reply-To: $mail_reply_to
Cc: $mail_cc
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=\"MULTIPART-MIXED-BOUNDARY\"

--MULTIPART-MIXED-BOUNDARY
Content-Type: multipart/alternative; boundary=\"MULTIPART-ALTERNATIVE-BOUNDARY\"

--MULTIPART-ALTERNATIVE-BOUNDARY
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: base64
Content-Disposition: inline

$message_base64
--MULTIPART-ALTERNATIVE-BOUNDARY--" > "$file_upload"

# add an image with corresponding content-id (here admin.png)
image_base64=$(curl -s "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_116x41dp.png" | base64)
add_file "image/png" "admin.png" "$image_base64"

# add the log file
log_file=$(cat log.txt | base64)
add_file "text/plain" "" "$log_file" "log.txt"

# add another image
#image_base64=$(curl -s "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_116x41dp.png" | base64)
#add_file "image/png" "something.png" "$image_base64"

# end of uploaded file
echo "--MULTIPART-MIXED-BOUNDARY--" >> "$file_upload"

# send email
echo "sending ...."
curl -s "$rtmp_url" \
--mail-from "$rtmp_from" \
--mail-rcpt "$rtmp_to" \
--ssl -u "$rtmp_credentials" \
-T "$file_upload" -k --anyauth
res=$?
if test "$res" != "0"; then
echo "sending failed with: $res"
else
echo "OK"
fi


Related Topics



Leave a reply



Submit