Can you tell me a code to implement in a c++ core that send backup/system information to a mail / gmail account?Those should be done on FreBSD 9.2+
// SMTPSend.c
//
// Created by Dr. Rolf Jansen on 2011-05-04.
// Copyright 2011-2014 Dr. Rolf Jansen. All rights reserved.
//
// cc SMTPSend.c -std=c99 -Os -o SMTPSend
// Standard C includes
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
// header files which must be included for
// high level DNS services and socket connections
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// constants
#define defaultBufferSize 4096
short doSMTPTransaction(int smtpSocket, char *sendBuffer, long sendBufferSize, char *receiveBuffer)
{
long receiveSize = 0;
if (sendBuffer && send(smtpSocket, sendBuffer, sendBufferSize, 0) == -1)
return 1000;
else if (receiveBuffer && (receiveSize = recv(smtpSocket, receiveBuffer, defaultBufferSize - 1, 0)) < 0)
return 2000;
if (receiveSize != 0)
{
receiveBuffer[receiveSize] = '\0';
return strtol(receiveBuffer, NULL, 10);
}
else
return 0;
}
// argv[1]: fully qualified sender address
// argv[2..n]: fully qualified recipient addresses
int main(int argc, const char *argv[])
{
int i, smtpCode = 0, resultCode = 1;
long smtpSocket, sendBufferSize;
char c = 0;
char transferBuffer[defaultBufferSize];
struct sockaddr_in address;
struct hostent *host = NULL;
char *smtpRelayHostName = "smtp.example.com"; // replace with the IP or address of the relay server
char *smtpAuthLoginID = "YXVzZXJpZEBleGFtcGxlLmNvbQo=\r\n"; // replace with your base 64 encoded SMTP login ID
char *smtpAuthPassword = "dGhlbW9zdHNlY3JldHBhc3N3b3JkZXZlcgo=\r\n"; // replace with your base 64 encoded SMTP auth password
if (!inet_aton(smtpRelayHostName, &address.sin_addr))
if (host = gethostbyname(smtpRelayHostName))
address.sin_addr = *(struct in_addr*)host->h_addr;
else
goto finish;
address.sin_port = htons(587);
address.sin_family = AF_INET;
if ((smtpSocket = socket(AF_INET, SOCK_STREAM, 0)) != -1)
{
if (connect(smtpSocket, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) != -1)
{
if ((smtpCode = doSMTPTransaction(smtpSocket, NULL, 0, transferBuffer)) > 299)
goto closeSession;
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "EHLO %s\r\n", argv[1]);
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
sendBufferSize = sprintf(transferBuffer, "AUTH LOGIN\r\n");
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 334)
goto closeSession;
if ((smtpCode = doSMTPTransaction(smtpSocket, smtpAuthLoginID, strlen(smtpAuthLoginID), transferBuffer)) != 334)
goto closeSession;
if ((smtpCode = doSMTPTransaction(smtpSocket, smtpAuthPassword, strlen(smtpAuthPassword), transferBuffer)) != 235)
goto closeSession;
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "MAIL FROM:<%s>\r\n", argv[1]);
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
for (i = 2; i < argc; i++)
{
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "RCPT TO:<%s>\r\n", argv[ i ]);
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
}
sendBufferSize = sprintf(transferBuffer, "DATA\r\n");
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) != 354)
goto closeSession;
while (c != EOF)
{
for (i = 0; i < defaultBufferSize && (c = fgetc(stdin)) != EOF; i++)
transferBuffer[ i ] = c;
smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, i, NULL);
}
sendBufferSize = sprintf(transferBuffer, "\r\n.\r\nQUIT\r\n");
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) == 250);
resultCode = 0;
closeSession:
close(smtpSocket);
}
}
finish:
if (resultCode)
syslog(LOG_ERR, "SMTPSend from %s to %s failed.", argv[1], argv[2]);
return resultCode;
}
Thx man, I will test and came back with a replyHere comes a simple SMTP sender that I wrote some years ago. It is in C, however it should be easily possible to make this into a sub-routine of a C++ project. The right to freely use it on your own risk with your project is granted herewith.
Code:// SMTPSend.c // // Created by Dr. Rolf Jansen on 2011-05-04. // Copyright 2011-2014 Dr. Rolf Jansen. All rights reserved. // // cc SMTPSend.c -std=c99 -Os -o SMTPSend // Standard C includes #include <stdlib.h> #include <string.h> #include <stdio.h> #include <stdbool.h> #include <errno.h> #include <unistd.h> #include <syslog.h> // header files which must be included for // high level DNS services and socket connections #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> // constants #define defaultBufferSize 4096 short doSMTPTransaction(int smtpSocket, char *sendBuffer, long sendBufferSize, char *receiveBuffer) { long receiveSize = 0; if (sendBuffer && send(smtpSocket, sendBuffer, sendBufferSize, 0) == -1) return 1000; else if (receiveBuffer && (receiveSize = recv(smtpSocket, receiveBuffer, defaultBufferSize - 1, 0)) < 0) return 2000; if (receiveSize != 0) { receiveBuffer[receiveSize] = '\0'; return strtol(receiveBuffer, NULL, 10); } else return 0; } // argv[1]: fully qualified sender address // argv[2..n]: fully qualified recipient addresses int main(int argc, const char *argv[]) { int i, smtpCode = 0, resultCode = 1; long smtpSocket, sendBufferSize; char c = 0; char transferBuffer[defaultBufferSize]; struct sockaddr_in address; struct hostent *host = NULL; char *smtpRelayHostName = "smtp.example.com"; // replace with the IP or address of the relay server char *smtpAuthLoginID = "YXVzZXJpZEBleGFtcGxlLmNvbQo=\r\n"; // replace with your base 64 encoded SMTP login ID char *smtpAuthPassword = "dGhlbW9zdHNlY3JldHBhc3N3b3JkZXZlcgo=\r\n"; // replace with your base 64 encoded SMTP auth password if (!inet_aton(smtpRelayHostName, &address.sin_addr)) if (host = gethostbyname(smtpRelayHostName)) address.sin_addr = *(struct in_addr*)host->h_addr; else goto finish; address.sin_port = htons(587); address.sin_family = AF_INET; if ((smtpSocket = socket(AF_INET, SOCK_STREAM, 0)) != -1) { if (connect(smtpSocket, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) != -1) { if ((smtpCode = doSMTPTransaction(smtpSocket, NULL, 0, transferBuffer)) > 299) goto closeSession; sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "EHLO %s\r\n", argv[1]); if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 299) goto closeSession; sendBufferSize = sprintf(transferBuffer, "AUTH LOGIN\r\n"); if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 334) goto closeSession; if ((smtpCode = doSMTPTransaction(smtpSocket, smtpAuthLoginID, strlen(smtpAuthLoginID), transferBuffer)) != 334) goto closeSession; if ((smtpCode = doSMTPTransaction(smtpSocket, smtpAuthPassword, strlen(smtpAuthPassword), transferBuffer)) != 235) goto closeSession; sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "MAIL FROM:<%s>\r\n", argv[1]); if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 299) goto closeSession; for (i = 2; i < argc; i++) { sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "RCPT TO:<%s>\r\n", argv[i]); if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 299) goto closeSession; } sendBufferSize = sprintf(transferBuffer, "DATA\r\n"); if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) != 354) goto closeSession; while (c != EOF) { for (i = 0; i < defaultBufferSize && (c = fgetc(stdin)) != EOF; i++) transferBuffer[i] = c; smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, i, NULL); } sendBufferSize = sprintf(transferBuffer, "\r\n.\r\nQUIT\r\n"); if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) == 250); resultCode = 0; closeSession: close(smtpSocket); } } finish: if (resultCode) syslog(LOG_ERR, "SMTPSend from %s to %s failed.", argv[1], argv[2]); return resultCode; } [/i][/i]
Wait a moment, I just realized, that by copying and pasting my code into the forum message editor, all the square brackets with i as the array index were removed. Please use the file, that I attached to this message.Thx man, I will test and came back with a reply
Thx again.Wheel the good news are that if I rename mail in mainMail ( to not have duplicate main definition) I get the core.Now the problem is how I can use it to send files/information at 6 hours to my mail?Wait a moment, I just realized, that by copying and pasting my code into the forum message editor, all the square brackets with i as the array index were removed. Please use the file, that I attached to this message.
(remove the .txt extension, the forum does not allow .c-files to be uploaded)
Thx again.Wheel the good news are that if I rename mail in mainMail ( to not have duplicate main definition) I get the core.Now the problem is how I can use it to send files/information at 6 hours to my mail?
./SMTPsend sender@example.com receiver@example.com < email-body.txt
int mainMail(const char *senderMailAddress, const char *receiverMailAddress)
{
...
...
FILE *mail_body_file = fopen("/path/to/email-body.txt", "r");
...
while (c != EOF)
{
for (i = 0; i < defaultBufferSize && (c = fgetc(mail_body_file)) != EOF; i++)
transferBuffer[ i ] = c;
smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, i, NULL);
}
...
fclose(mail_body_file);
...
}
...
int mainMail(const char *senderMailAddress, const char *receiverMailAddress, const char *mailBody, int mailBodySize)
{
...
smtpCode = doSMTPTransaction(smtpSocket, mailBody, mailBodySize, NULL);
... and also for username/pw you added to both of them at the end of encode of base 64 "\r\n" that doesn't affect the decodind,so I should add that too?
echo -n "mailadmin@example.com" | base64 -e
--> bWFpbGFkbWluQGV4YW1wbGUuY29t echo -n "a_totally_secret_password" | base64 -e
--> YV90b3RhbGx5X3NlY3JldF9wYXNzd29yZA==#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
// header files which must be included for
// high level DNS services and socket connections
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// constants
#define defaultBufferSize 4096
short doSMTPTransaction(int smtpSocket, char *sendBuffer, long sendBufferSize, char *receiveBuffer)
{
long receiveSize = 0;
if (sendBuffer && send(smtpSocket, sendBuffer, sendBufferSize, 0) == -1)
return 1000;
else if (receiveBuffer && (receiveSize = recv(smtpSocket, receiveBuffer, defaultBufferSize - 1, 0)) < 0)
return 2000;
if (receiveSize != 0)
{
receiveBuffer[receiveSize] = '\0';
return strtol(receiveBuffer, NULL, 10);
}
else
return 0;
}
// argv[2..n]: fully qualified recipient addresses
int mainMail() //no need (int argc, const char *argv[])
{
int i, smtpCode = 0, resultCode = 1;
long smtpSocket, sendBufferSize;
char c = 0;
char transferBuffer[defaultBufferSize];
const char *senderMailAddress="test@gmail.com";
const char *receiverMailAddress="test@gmail.com";
struct sockaddr_in address;
struct hostent *host = NULL;
char *smtpRelayHostName = "mail.google.com";
char *smtpAuthLoginID = "base64encoded\r\n";
char *smtpAuthPassword = "base64encoded\r\n";
FILE *mail_body_file = fopen("/path/to/email-body.txt", "r");
while (c != EOF)
{
for (i = 0; i < defaultBufferSize && (c = fgetc(mail_body_file)) != EOF; i++)
transferBuffer[ i ] = c;
smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, i, NULL);
}
fclose(mail_body_file);
if (!inet_aton(smtpRelayHostName, &address.sin_addr))
if (host = gethostbyname(smtpRelayHostName))
address.sin_addr = *(struct in_addr*)host->h_addr;
// else
// goto finish;
address.sin_port = htons(587);
address.sin_family = AF_INET;
if ((smtpSocket = socket(AF_INET, SOCK_STREAM, 0)) != -1)
{
if (connect(smtpSocket, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) != -1)
{
if ((smtpCode = doSMTPTransaction(smtpSocket, NULL, 0, transferBuffer)) > 299)
goto closeSession;
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "EHLO %s\r\n", senderMailAddress);
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
sendBufferSize = sprintf(transferBuffer, "AUTH LOGIN\r\n");
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 334)
goto closeSession;
if ((smtpCode = doSMTPTransaction(smtpSocket, smtpAuthLoginID, strlen(smtpAuthLoginID), transferBuffer)) != 334)
goto closeSession;
if ((smtpCode = doSMTPTransaction(smtpSocket, smtpAuthPassword, strlen(smtpAuthPassword), transferBuffer)) != 235)
goto closeSession;
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "MAIL FROM:<%s>\r\n", senderMailAddress);
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "RCPT TO:<%s>\r\n", receiverMailAddress);
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
/*
for (i = 3; i < argc; i++)
{
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "RCPT TO:<%s>\r\n", argv[i]);
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
}
*/
sendBufferSize = sprintf(transferBuffer, "DATA\r\n");
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) != 354)
goto closeSession;
while (c != EOF)
{
for (i = 0; i < defaultBufferSize && (c = fgetc(stdin)) != EOF; i++)
transferBuffer[i] = c;
smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, i, NULL);
}
sendBufferSize = sprintf(transferBuffer, "\r\n.\r\nQUIT\r\n");
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) == 250);
resultCode = 0;
closeSession:
close(smtpSocket);
}
}
//finish:
// if (resultCode)
// syslog(LOG_ERR, "SMTPSend from %s to %s failed.", senderMailAddress, argv[2]);
return resultCode;
}
[/i][/i]
Are you really sure, that you want this SMTP sender being part of your C++ program. Why don't you simply use it as a standalone tool and add a line to /etc/crontab:Thanks a lot ,so I make some changes and came back with a feedback.Also how I can make this function to auto repeat every 6 hours?
...
0 */6 * * * root /usr/local/bin/SMTPSend sender@gmail.com rcvr1@gmail.com rcvr2@gmail.com rcvr3@gmail.com < /path/to/email-body.txt
Also why you defined
const char *senderMailAddress
as a pointer? A simple const char is not better?
Also I want the email to be sent from me to me, the user and pw that I put there are from FreeBSD host, not from gmail acc?
// SMTPSend.c
//
// Created by Dr. Rolf Jansen on 2011-05-04.
// Copyright 2011-2016 Dr. Rolf Jansen. All rights reserved.
//
// cc SMTPSend.c -std=c11 -Os -g0 -Wno-parentheses -Wno-dangling-else -Wno-empty-body -lcrypto -lssl -o SMTPSend
// Standard C includes
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
// header files which must be included for
// high level DNS services and socket connections
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// OpenSSL header
#include <openssl/ssl.h>
// constants
#define defaultBufferSize 65536
short tlsSMTPTransaction(SSL *ssl, char *sendBuffer, long sendBufferSize, char *receiveBuffer)
{
long receiveSize = 0;
if (sendBuffer && SSL_write(ssl, sendBuffer, sendBufferSize) < 0)
return 1000;
else if (receiveBuffer && (receiveSize = SSL_read(ssl, receiveBuffer, defaultBufferSize - 1)) < 0)
return 2000;
if (receiveSize != 0)
{
receiveBuffer[receiveSize] = '\0';
return strtol(receiveBuffer, NULL, 10);
}
else
return 0;
}
// argv[1]: fully qualified sender address
// argv[2..n]: fully qualified recipient addresses
int main(int argc, const char *argv[])
{
int k, smtpCode = 0, resultCode = 1;
long smtpSocket, sendBufferSize;
char c = 0;
char transferBuffer[defaultBufferSize];
struct sockaddr_in address;
struct hostent *host = NULL;
char *smtpRelayHostName = "smtp.gmail.com"; // replace with the IP or address of the relay server
char *smtpAuthLoginID = "base64LoginID\r\n"; // replace with your base 64 encoded SMTP login ID
char *smtpAuthPassword = "base64Password\r\n"; // replace with your base 64 encoded SMTP auth password
if (!inet_aton(smtpRelayHostName, &address.sin_addr))
if (host = gethostbyname(smtpRelayHostName))
address.sin_addr = *(struct in_addr*)host->h_addr;
else
goto finish;
address.sin_port = htons(465);
address.sin_family = AF_INET;
if ((smtpSocket = socket(AF_INET, SOCK_STREAM, 0)) != -1)
{
if (connect(smtpSocket, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) != -1)
{
// TLS preparation
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_client_method());
if (!ctx)
goto closeSocket;
SSL *ssl = SSL_new(ctx);
SSL_set_fd(ssl, smtpSocket);
if (SSL_connect(ssl) == -1)
goto closeSession;
if ((smtpCode = tlsSMTPTransaction(ssl, NULL, 0, transferBuffer)) > 299)
goto closeSession;
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "EHLO %s\r\n", argv[1]);
if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
sendBufferSize = sprintf(transferBuffer, "AUTH LOGIN\r\n");
if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) > 334)
goto closeSession;
if ((smtpCode = tlsSMTPTransaction(ssl, smtpAuthLoginID, strlen(smtpAuthLoginID), transferBuffer)) != 334)
goto closeSession;
if ((smtpCode = tlsSMTPTransaction(ssl, smtpAuthPassword, strlen(smtpAuthPassword), transferBuffer)) != 235)
goto closeSession;
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "MAIL FROM:<%s>\r\n", argv[1]);
if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
for (k = 2; k < argc; k++)
{
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "RCPT TO:<%s>\r\n", argv[k]);
if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
}
sendBufferSize = sprintf(transferBuffer, "DATA\r\n");
if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) != 354)
goto closeSession;
while (c != EOF)
{
for (k = 0; k < defaultBufferSize && (c = fgetc(stdin)) != EOF; k++)
transferBuffer[k] = c;
smtpCode = tlsSMTPTransaction(ssl, transferBuffer, k, NULL);
}
sendBufferSize = sprintf(transferBuffer, "\r\n.\r\nQUIT\r\n");
if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) == 250);
resultCode = 0;
closeSession:
SSL_free(ssl);
SSL_CTX_free(ctx);
closeSocket:
close(smtpSocket);
}
}
finish:
if (resultCode)
syslog(LOG_ERR, "SMTPSend from %s to %s failed.", argv[1], argv[2]);
return resultCode;
}
Thanks again for your time and support,I want it to run inside a game core so I can push the logs directly to email and would be more easy and I could have more options inside than outside,for this reason I wanted to know if for that TLS enabled version of SMTPSend code I can just say from begin that the sender/receiver is me and the function just to be likeAre you really sure, that you want this SMTP sender being part of your C++ program. Why don't you simply use it as a standalone tool and add a line to /etc/crontab:
In this case your C++ program would write diagnostic messages to the file, and SMTPSend would be launched every 6 hours as a cronjob and would send the diagnostics to the receiver address(es).Code:... 0 */6 * * * root /usr/local/bin/SMTPSend sender@gmail.com rcvr1@gmail.com rcvr2@gmail.com rcvr3@gmail.com < /path/to/email-body.txt
If this must be part of your C++ program, then I would create a POSIX thread running an infinite loop, whose body would call the SMTPSend() function and then would go to sleep(3) for 6 hours.
const char would be a single character, and this is definitely not what is needed here.
The user would be the fully qualified gmail address, and the password would be that of your gmail account. BTW, the GMAIL SMTP server requires TLS, and for this reason the plain SMTPSend tool does not work with gmail. See here: https://support.google.com/a/answer/176600?hl=en
Here comes the source code of a TLS enabled version of SMTPSend:
Code:// SMTPSend.c // // Created by Dr. Rolf Jansen on 2011-05-04. // Copyright 2011-2016 Dr. Rolf Jansen. All rights reserved. // // cc SMTPSend.c -std=c11 -Os -g0 -Wno-parentheses -Wno-dangling-else -Wno-empty-body -lcrypto -lssl -o SMTPSend // Standard C includes #include <stdlib.h> #include <string.h> #include <stdio.h> #include <stdbool.h> #include <errno.h> #include <unistd.h> #include <syslog.h> // header files which must be included for // high level DNS services and socket connections #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> // OpenSSL header #include <openssl/ssl.h> // constants #define defaultBufferSize 65536 short tlsSMTPTransaction(SSL *ssl, char *sendBuffer, long sendBufferSize, char *receiveBuffer) { long receiveSize = 0; if (sendBuffer && SSL_write(ssl, sendBuffer, sendBufferSize) < 0) return 1000; else if (receiveBuffer && (receiveSize = SSL_read(ssl, receiveBuffer, defaultBufferSize - 1)) < 0) return 2000; if (receiveSize != 0) { receiveBuffer[receiveSize] = '\0'; return strtol(receiveBuffer, NULL, 10); } else return 0; } // argv[1]: fully qualified sender address // argv[2..n]: fully qualified recipient addresses int main(int argc, const char *argv[]) { int k, smtpCode = 0, resultCode = 1; long smtpSocket, sendBufferSize; char c = 0; char transferBuffer[defaultBufferSize]; struct sockaddr_in address; struct hostent *host = NULL; char *smtpRelayHostName = "smtp.gmail.com"; // replace with the IP or address of the relay server char *smtpAuthLoginID = "base64LoginID\r\n"; // replace with your base 64 encoded SMTP login ID char *smtpAuthPassword = "base64Password\r\n"; // replace with your base 64 encoded SMTP auth password if (!inet_aton(smtpRelayHostName, &address.sin_addr)) if (host = gethostbyname(smtpRelayHostName)) address.sin_addr = *(struct in_addr*)host->h_addr; else goto finish; address.sin_port = htons(465); address.sin_family = AF_INET; if ((smtpSocket = socket(AF_INET, SOCK_STREAM, 0)) != -1) { if (connect(smtpSocket, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) != -1) { // TLS preparation SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_client_method()); if (!ctx) goto closeSocket; SSL *ssl = SSL_new(ctx); SSL_set_fd(ssl, smtpSocket); if (SSL_connect(ssl) == -1) goto closeSession; if ((smtpCode = tlsSMTPTransaction(ssl, NULL, 0, transferBuffer)) > 299) goto closeSession; sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "EHLO %s\r\n", argv[1]); if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) > 299) goto closeSession; sendBufferSize = sprintf(transferBuffer, "AUTH LOGIN\r\n"); if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) > 334) goto closeSession; if ((smtpCode = tlsSMTPTransaction(ssl, smtpAuthLoginID, strlen(smtpAuthLoginID), transferBuffer)) != 334) goto closeSession; if ((smtpCode = tlsSMTPTransaction(ssl, smtpAuthPassword, strlen(smtpAuthPassword), transferBuffer)) != 235) goto closeSession; sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "MAIL FROM:<%s>\r\n", argv[1]); if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) > 299) goto closeSession; for (k = 2; k < argc; k++) { sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "RCPT TO:<%s>\r\n", argv[k]); if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) > 299) goto closeSession; } sendBufferSize = sprintf(transferBuffer, "DATA\r\n"); if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) != 354) goto closeSession; while (c != EOF) { for (k = 0; k < defaultBufferSize && (c = fgetc(stdin)) != EOF; k++) transferBuffer[k] = c; smtpCode = tlsSMTPTransaction(ssl, transferBuffer, k, NULL); } sendBufferSize = sprintf(transferBuffer, "\r\n.\r\nQUIT\r\n"); if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) == 250); resultCode = 0; closeSession: SSL_free(ssl); SSL_CTX_free(ctx); closeSocket: close(smtpSocket); } } finish: if (resultCode) syslog(LOG_ERR, "SMTPSend from %s to %s failed.", argv[1], argv[2]); return resultCode; }
Yes!... I wanted to know if for that TLS enabled version of SMTPSend code I can just say from begin that the sender/receiver is me ...
No, you must not omit the minimum SMTP protocol sequence consisting of EHLO, AUTH LOGIN, MAIL FROM:, RCPT TO:, DATA. Your log message shall come only after a successful DATA transaction.... and the function just to be like
tlsSMTPTransaction(logs)
Interesting!Advertisement for the "new" MSG_NOSIGNAL flag of send(2).
int optval = 1;
setsockopt(sockdesc, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(int));
So mainMail(sender@gmail.com,rcvr1@gmail.com); is the called function and should work? I need only a call example and is enough I guess
http://prntscr.com/9lncfo
// SMTPSend.c
//
// Created by Dr. Rolf Jansen on 2011-05-04.
// Copyright 2011-2016 Dr. Rolf Jansen. All rights reserved.
//
// cc SMTPSend.c -std=c11 -Os -g0 -Wno-parentheses -Wno-dangling-else -Wno-empty-body -I/usr/local/include -L/usr/local/lib -lcrypto -lssl -o SMTPSend
// Standard C includes
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <time.h>
#include <sys/stat.h>
// header files which must be included for
// high level DNS services and socket connections
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// OpenSSL headers
#include <openssl/ssl.h>
// constants
#define defaultBufferSize 65536
int tlsSMTPTransaction(SSL *ssl, const char *sendBuffer, int sendBufferSize, char *receiveBuffer)
{
long receiveSize = 0;
if (sendBuffer && SSL_write(ssl, sendBuffer, sendBufferSize) <= 0)
return 1000;
else if (receiveBuffer && (receiveSize = SSL_read(ssl, receiveBuffer, defaultBufferSize - 1)) <= 0)
return 2000;
if (receiveSize)
{
receiveBuffer[receiveSize] = '\0';
return strtol(receiveBuffer, NULL, 10);
}
else
return 0;
}
int SMTPSend(const char *sender,
const char *receiver,
const char *subject,
const char *message,
int messageSize)
{
int smtpCode = 0, resultCode = 1;
int smtpSocket, sendBufferSize;
char transferBuffer[defaultBufferSize];
struct sockaddr_in address;
struct hostent *host = NULL;
char *smtpRelayHostName = "smtp.gmail.com"; // replace with the IP or address of the relay server
char *smtpAuthLoginID = "dXNlckBnbWFpbC5jb20=\r\n"; // user@gmail.com -- replace with your base 64 encoded SMTP login ID
char *smtpAuthPassword = "U2VjcmV0IFBhc3N3b3Jk\r\n"; // Secret Password -- replace with your base 64 encoded SMTP auth password
if (!inet_aton(smtpRelayHostName, &address.sin_addr))
if (host = gethostbyname(smtpRelayHostName))
address.sin_addr = *(struct in_addr*)host->h_addr;
else
goto finish;
address.sin_port = htons(465);
address.sin_family = AF_INET;
if ((smtpSocket = socket(AF_INET, SOCK_STREAM, 0)) != -1)
{
if (connect(smtpSocket, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) != -1)
{
// TLS preparation
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_client_method());
if (!ctx)
goto closeSocket;
SSL *ssl = SSL_new(ctx);
SSL_set_fd(ssl, smtpSocket);
if (SSL_connect(ssl) == -1)
goto closeSession;
if ((smtpCode = tlsSMTPTransaction(ssl, NULL, 0, transferBuffer)) > 299)
goto closeSession;
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "EHLO %s\r\n", sender);
if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
sendBufferSize = sprintf(transferBuffer, "AUTH LOGIN\r\n");
if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) > 334)
goto closeSession;
if ((smtpCode = tlsSMTPTransaction(ssl, smtpAuthLoginID, strlen(smtpAuthLoginID), transferBuffer)) != 334)
goto closeSession;
if ((smtpCode = tlsSMTPTransaction(ssl, smtpAuthPassword, strlen(smtpAuthPassword), transferBuffer)) != 235)
goto closeSession;
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "MAIL FROM:<%s>\r\n", sender);
if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "RCPT TO:<%s>\r\n", receiver);
if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
sendBufferSize = sprintf(transferBuffer, "DATA\r\n");
if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) != 354)
goto closeSession;
time_t tod = time(NULL);
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "From: %s\nTo: %s\nDate: %sSubject: %s\n\n", sender, receiver, ctime(&tod), subject);
if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, NULL)) == 1000)
goto closeSession;
if ((smtpCode = tlsSMTPTransaction(ssl, message, messageSize, NULL)) == 1000)
goto closeSession;
sendBufferSize = sprintf(transferBuffer, "\r\n.\r\nQUIT\r\n");
if ((smtpCode = tlsSMTPTransaction(ssl, transferBuffer, sendBufferSize, transferBuffer)) == 250);
resultCode = 0;
closeSession:
SSL_free(ssl);
SSL_CTX_free(ctx);
closeSocket:
close(smtpSocket);
}
}
finish:
if (resultCode)
syslog(LOG_ERR, "SMTPSend from %s to %s failed.", sender, receiver);
return resultCode;
}
int main(int argc, const char *argv[])
{
int rc = 1;
struct stat st;
if (stat(argv[1], &st) == 0)
{
FILE *logfile = fopen(argv[1], "r");
if (logfile)
{
char *message = malloc(st.st_size + 1);
if (message)
{
if (fread(message, st.st_size, 1, logfile) == 1)
{
// sanity measure, add a trailing nul at the very end of the message
message[st.st_size] = '\0';
// sender address receiver address subject message size
rc = SMTPSend("user@gmail.com", "user@gmail.com", "This is a Test.", message, (int)st.st_size);
}
free(message);
}
fclose(logfile);
}
}
return rc;
}
No, this comes because you try to compile C code as C++ code, and in cases, C++ exaggerates the nit-picking.I think that I need to update some libraries
http://prntscr.com/9ly0p8
SSL_CTX *ctx;
SSL *ssl;
time_t tod;
// TLS preparation
...
main.o: In function `tlsSMTPTransaction(ssl_st*, char const*, int, char*)':
Mail.cpp:96: multiple definition of `tlsSMTPTransaction(ssl_st*, char const*, int, char*)'
Mail.cpp:96: first defined here
main.o: In function `SMTPSend(char const*, char const*, char const*, char const*, int)':
Mail.cpp:121: multiple definition of `SMTPSend(char const*, char const*, char const*, char const*, int)'
Mail.cpp:121: first defined here
Mail.o: In function `tlsSMTPTransaction(ssl_st*, char const*, int, char*)':
Mail.cpp:(.text+0x2f): undefined reference to `SSL_write'
Mail.cpp:(.text+0x52): undefined reference to `SSL_read'
Mail.o: In function `SMTPSend(char const*, char const*, char const*, char const*, int)':
Mail.cpp:(.text+0x16d): undefined reference to `SSL_library_init'
Mail.cpp:(.text+0x177): undefined reference to `OpenSSL_add_all_algorithms'
Mail.cpp:(.text+0x17c): undefined reference to `SSL_load_error_strings'
Mail.cpp:(.text+0x181): undefined reference to `TLSv1_2_client_method'
Mail.cpp:(.text+0x189): undefined reference to `SSL_CTX_new'
Mail.cpp:(.text+0x19b): undefined reference to `SSL_new'
Mail.cpp:(.text+0x1a9): undefined reference to `SSL_set_fd'
Mail.cpp:(.text+0x1b1): undefined reference to `SSL_connect'
Mail.cpp:(.text+0x1ec): undefined reference to `SSL_free'
Mail.cpp:(.text+0x1fa): undefined reference to `SSL_CTX_free'
main.o: In function `tlsSMTPTransaction(ssl_st*, char const*, int, char*)':
main.cpp:(.text+0x73f): undefined reference to `SSL_write'
main.cpp:(.text+0x762): undefined reference to `SSL_read'
main.o: In function `SMTPSend(char const*, char const*, char const*, char const*, int)':
main.cpp:(.text+0x87d): undefined reference to `SSL_library_init'
main.cpp:(.text+0x887): undefined reference to `OpenSSL_add_all_algorithms'
main.cpp:(.text+0x88c): undefined reference to `SSL_load_error_strings'
main.cpp:(.text+0x891): undefined reference to `TLSv1_2_client_method'
main.cpp:(.text+0x899): undefined reference to `SSL_CTX_new'
main.cpp:(.text+0x8ab): undefined reference to `SSL_new'
main.cpp:(.text+0x8b9): undefined reference to `SSL_set_fd'
main.cpp:(.text+0x8c1): undefined reference to `SSL_connect'
main.cpp:(.text+0x8fc): undefined reference to `SSL_free'
main.cpp:(.text+0x90a): undefined reference to `SSL_CTX_free'