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
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <iostream>
#define _SMTP_PORT 25
#define _SMTP_BUFFERSIZE 1'000
#define _SMTP_DE_de "smtpout.asia.secureserver.net"
char *getipbydom(const char *domain)
{
char *target_ip{nullptr};
struct in_addr *host_addr;
struct hostent *raw_list = gethostbyname(domain);
for (int i = 0; raw_list->h_addr_list[i] != 0; i++)
{
host_addr = (in_addr *) raw_list->h_addr_list[i];
target_ip = inet_ntoa(*host_addr);
}
return target_ip;
}
class SMTP {
const char *_smtp_server_addr = nullptr;
int _smtp_socket{-1};
void _server_init() {
int sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(_SMTP_PORT);
if (inet_pton(AF_INET, getipbydom(_smtp_server_addr), &addr.sin_addr) == 1)
connect(sock_fd, (const sockaddr*) &addr, sizeof(addr));
else
throw std::invalid_argument("cannot reach smtp server\n"
"please check your input and/or internet connection");
_smtp_socket = sock_fd;
}
void write_server(std::string msg)
{
char *_buf = new char[_SMTP_BUFFERSIZE]{};
strcat(_buf, msg.c_str());
send(_smtp_socket, _buf, _SMTP_BUFFERSIZE, 0);
delete[] _buf;
}
std::pair<int, std::string> read_server()
{
char *_buf{new char[_SMTP_BUFFERSIZE]{}};
recv(_smtp_socket, _buf, _SMTP_BUFFERSIZE, 0);
auto ret{std::make_pair(atoi(std::string{_buf}.substr(0, 3).c_str()), std::string(_buf))};
delete[] _buf;
return ret;
}
public:
enum STATUS_CODE{SYSTEM_STATUS_HELP_REPLY=211, HELP=214, SERVER_READY=220, CONNECTION_CLOSED=221, EXECUTED_COMMAND=250,
FOWARDPATH=251 /* no messages waiting for node, user not local*/, CANNOT_VERYFY_USER=252, OK_MESSAGES_PENDING=253,
MAIL_RECEIVE_START=354 /* end with <CRLF>.<CRLF> */, OCTET_TRANSACTION_OFFSET=355, SERVICE_NOT_AVAILABLE=421, PASSWORT_TRANSITOIN_NEEDED=432,
ACTION_NOT_TAKEN_MAILBOX_UNAVAILABLE=450, REQUEST_ABORTED=451 /* error in processing */, INSUFFICIENT_SYSTEM_STORAGE=452,
NO_EMAIL=453, TLS_TEMPORARY_UNAVAILABLE=454, UNABLE_TO_QUEUE=458, NODE_FORBIDDEN, UNKNOWN_COMMAND_SYNTAX, SYNTAX_ERROR /* params incorrect */,
UNKNOWN_COMMAND, BAD_SEQUENCE, UNKNOWN_PARAM, NO_ACCEPT_MAIL=521, STARTTLS_REQUIRED=530 /* encryption required */, AUTH_MECHANISM_WEAK=534,
ENCRYPTION_REQUIRED=538, REQUEST_NOT_TAKEN=550, USER_UNLOCAL, EXCEEDED_STORAGE_ALLOCATION, MAILBOX_NAME_FORBIDDEN, TRANSACTION_FAILED};
SMTP (const char *smtp_server_addr = _SMTP_DE_de): _smtp_server_addr{smtp_server_addr}
{
if (getipbydom(_smtp_server_addr) == nullptr)
throw std::invalid_argument("bad smtp server address given");
std::cout << "SMTP SERVER IS " << _smtp_server_addr << "\n";
_server_init();
std::cout << "CONNECTED ON " << _smtp_socket << "\n";
std::cout << "[+] " << read_server().second;
write_server("HELO server\r\n");
std::cout << "HELO server: " << read_server().second;
write_server("AUTH LOGIN\r\n");
std::cout << read_server().second;
}
~SMTP()
{
if (_smtp_socket == -1)
return;
write_server("QUIT \r\n"); // sending QUIT command to server to abort connection
std::cout << "[-] " << read_server().second;
close(_smtp_socket); // connection closure
}
};
|