Как отправить почту с использованием сокета C ++ - PullRequest
0 голосов
/ 06 октября 2019

Я использую сокет для отправки почты из моего аккаунта Gmail на мой аккаунт Gmail, чтобы избежать SSL и аутентификации, но я не знаю, блокирует ли Gmail эти порты для TLS (из-за спама), потому что я ничего не получаютакже папка спама пуста.

Если у кого-то есть опыт в этой теме, я был бы благодарен.

int main() {

    cout << "send mail" << endl;

    char arr[] = "gmail-smtp-in.l.google.com";
    char* ptrServer = arr;
    char arr0[] = "someaddress@gmail.com";
    char* ptrReceiver= arr0;
    char arr1[] = "someaddress@gmail.com";
    char* ptrSender = arr1;
    char arr2[] = "- Some Data -";
    char* ptrSubject = arr2; 
    char arr3[] = "Hello from the PC";
    char* ptrMessage = arr3;

    sendEmail(ptrServer, ptrReceiver, ptrSender, ptrSubject, ptrMessage);

    cin >> arr;
    return 0;
}

Вот функция, которую я использую для отправки почты (я не знаю точно, что вынужно отправить по TLS, я просто отправляю эту последовательность EHLO и STARTTLS)

void sendEmail(char * server, char * to, char * from, char * subject, char * message) {


    SOCKET sockfd;
    WSADATA wsaData;
    hostent* host;
    sockaddr_in dest;



    char szSmtpServerName[64] = "";
    int sent;
    char line[256];

    if (WSAStartup(0x202, &wsaData) != SOCKET_ERROR) {
        if ((host = gethostbyname(server)) != NULL) {
            memset(&dest, 0, sizeof(dest));
            memcpy(&(dest.sin_addr), host->h_addr, host->h_length);

            dest.sin_family = host->h_addrtype;
            dest.sin_port = htons(25);

            sockfd = socket(AF_INET, SOCK_STREAM, 0);


            connect(sockfd, (struct sockaddr*) & dest, sizeof(dest));


            strcpy_s(line, "EHLO\n"); 
            sent=send(sockfd, line, strlen(line),0);
            Sleep(500);

            strcpy_s(line, "STARTTLS\n");
            sent = send(sockfd, line, strlen(line), 0);
            Sleep(500);

            strcpy_s(line, "MAIL FROM:<");
            strncat_s(line, from, strlen(from));
            strncat_s(line, ">\n", 3);
            sent = send(sockfd, line, strlen(line), 0);
            Sleep(500);


            strcpy_s(line, "RCPT TO:<");
            strncat_s(line, to, strlen(to));
            strncat_s(line, ">\n", 3);
            sent = send(sockfd, line, strlen(line), 0);
            Sleep(500);

            strcpy_s(line, "DATA\n");
            sent = (send(sockfd, line, strlen(line), 0));
            Sleep(500);


            strcpy_s(line, "To: ");
            strcat_s(line, to);
            strcat_s(line, "\n");
            strcat_s(line, "From: ");
            strcat_s(line, from);
            strcat_s(line, "\n");
            strcat_s(line, "Subject: ");
            strcat_s(line, subject);
            strcat_s(line, "\n");
            strcat_s(line, message);
            strcat_s(line, "\r\n.\r\n");
            sent = send(sockfd, line, strlen(line), 0);
            Sleep(500);

            strcpy_s(line, "quit\n");
            sent = send(sockfd, line, strlen(line), 0);
            Sleep(500);

        }

    }
    closesocket(sockfd);
    WSACleanup();
    cout << "mail was sent" << endl;
}

1 Ответ

0 голосов
/ 06 октября 2019

Полная спецификация SMTP является общедоступным документом . Если вы просмотрите эти формальные спецификации для SMTP, вы легко обнаружите ряд фундаментальных проблем с показанным кодом.

1) После установления соединения отправитель должен дождаться начального приветствия сервера. Показанный код немедленно отправляет команду EHLO без ожидания.

2) После отправки команды EHLO отправитель должен дождаться ответа сервера, а не ждать 500 миллисекунд, и обработать ответ.

3) Команда EHLO может завершиться ошибкой, поскольку она является расширением;если это так, отправитель должен вернуться к HELO. Маловероятно, с современными SMTP-серверами, но то, что должна быть подготовлена ​​надежной программой.

4) Во всех случаях ответ сервера может указывать на ошибку и / или отказ принимать почту. Показанный код не может выполнить какую-либо проверку ошибок.

5) После отправки команды STARTTLS отправитель должен дождаться ответа сервера, и, если команда выполнена успешно, отправитель должен инициировать согласование TLS. Показанный код не может этого сделать.

6) После того, как состоялось согласование TLS и установлено зашифрованное соединение, сеанс SMTP перезапускается из исходного состояния, из состояния EHLO / HELO вместо MAIL FROM.

Вместо правильной обработки ответов сервера вы не можете использовать любые простые ярлыки, например, спать в течение определенного предписанного периода времени. Это не будет надежно работать с течением времени. Может показаться, что это работает, один или два раза, но в конечном итоге сломается. Это гарантия. Вы должны правильно и полностью внедрить каждую часть SMTP и правильно ее реализовать.

Поскольку вы используете Microsoft Windows, вы должны найти полную документацию по использованию TLS в MS-Windows в документации Microsoft. Очевидно, что это очень большая тема, которая просто не будет скопирована дословно в этот ответ или любой другой ответ по Stackoverflow. Для получения дополнительной информации см. Документацию Microsoft по MSDN или где-либо еще.

Все это довольно сложные, большие технические вопросы программирования. Вы не найдете полное описание их, сведенное к полному ответу в один или два абзаца на Stackoverflow или любом другом общедоступном форуме. Единственное, что любой сможет вам сказать, это обратиться к технической документации для полной спецификации того, как работает тот или иной протокол. Знание, где найти и как читать техническую документацию - это то, что каждый разработчик C ++ должен знать, как это сделать.

Вы также, вероятно, обнаружите, что MS-Windows может предложить клиентскую библиотеку SMTP, которая правильно и правильнообрабатывает все аспекты SMTP, включая TLS, не беспокоясь о вашем коде. А наличие или отсутствие такой клиентской библиотеки SMTP - это то, что вы сможете определить только после ознакомления с технической документацией Microsoft.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...