SMTP SendMail Help

closed account (3Tpi3vqX)
Hello guys,

i need help to finish my smtp library because i keep getting error messages from the SMTP server. Heres my code:

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
    }

};


At the moment, as i call a new object of my class,
the following happens.
1
2
3
4
5
6
7
8
SMTP SERVER IS smtpout.asia.secureserver.net
CONNECTED ON 3
[+] 220 p3plsmtpa08-07.prod.phx3.secureserver.net :SMTPAUTH: Jx7vojw55hd8d : ESMTP server p3plsmtpa08-07.prod.phx3.secureserver.net ready
HELO server: 250 p3plsmtpa08-07.prod.phx3.secureserver.net hello [149.172.127.122], secureserver.net
500 bad chars in command
[-] 500 bad chars in command

Process finished with exit code 0


Can anyone help me please.

Thanks a lot.

Luke
> char *_buf = new char[_SMTP_BUFFERSIZE]{};
Does this guarantee that the buffer begins with a \0?

> strcat(_buf, msg.c_str());
What if the string doesn't fit, you trash memory.

> send(_smtp_socket, _buf, _SMTP_BUFFERSIZE, 0);
How about sending just the valid characters, instead of up to 1000 bytes of who knows what.

In addition, you need to check the return result of send() to make sure all the characters were sent.

The same applies to recv().
Make sure you have a valid buffer before blindly assuming success.

Yes you are right with the sent bytes check. Ive implemented wrappers for that in another file, but didnt want to share them. So i replaced the wrapper calls with the basic send and recv function expediantly. The only problem is, that i get an 500 bad chars error.
Last edited on
LukeProducts wrote:
this does not help at all.

Well, you aren't the OP, are you? Two different accounts is not good netiquette.
> So i replaced the wrapper calls with the basic send and recv function expediantly.
> The only problem is, that i get an 500 bad chars error.
In other words, you're wasting everyone's time.

Posting a broken facsimile of your problem isn't likely to solve the real problem.

> Thanks, but this does not help at all.
salem c (3516) Aug 5, 2022 at 3:00pm
LukeProducts (22) Aug 5, 2022 at 3:10pm
So allowing for various lags in the board sending a notification, you reading a notification, you reading my message and you composing your missive, just how much time did you spend trying the suggestions?
There's not a lot left for actual work on your part in those 10 minutes.

> Youre yust telling me what i did wrong.
Gee, if you were expecting a fully working copy/paste job, you're in the wrong place.
You wanted "help", you got "help".

We're your guides, not your mules.
I am sorry for this misunderstanding.
I highly respect you for the help you offer me, as you helped me with my question https://cplusplus.com/forum/windows/283369/ back then.
My question has been solved anyway, because in the function write_server I simply corrected the buffer size down to the original size of the message and did not leave it at 1000. I hope you have a nice day and can forgive me for the cheeky message.

With nice greetings

Luke
A couple of things to consider in the future when you ask for programming help:

http://www.gregcons.com/KateBlog/HowToAskForCCodingHelp.aspx

http://www.sscce.org/

Throw us some digital "catnip" in the correct manner and you won't have to worry about getting replies. Replies that are helpful and informative.

And useful for others as well who might have questions.
Registered users can post here. Sign in or register to post.