отправка писем с аттачем из лвс с kerio
От: Black_Moon  
Дата: 15.08.07 12:17
Оценка:
Написал smtp клиента
отправляю письма с аттачем.
Вот какую фичу заметил — аттачи до 8192 байт отправляются отлично, а если >= то при отправке выдает ошибку 10053 (WSAECONNABORTED). Прада если отправлять обычным клиентом (напр. The Bat!), то все ок. Аттачи отправляются кусками по 1364 байта (чтение файла в блоки по 1023 — потом кодирование base64).

Клиент работает на раб. станции в лвс, на сервере стоит winroute kerio.
Пробовал отправлять минуя kerio (подключая интернет напрямую к компу — все идет).

Через свой фтп-клиенет тоже никаких ограничений на файл нет...

Непонятно в каких настройках ковыряться?

Вот еще заметил — если адресат rambler.ru, то в полученый аттач принимает не верно. 1й блок декодирует верно, а перед остальными сам ставит "\r\n"

Код

#include <stdio.h>
#include <winsock2.h>
#include <windows.h>

#define BOUNDARY            "e1215f2aa8c6"

#define BLOCK_SIZE            1023
#define BLOCK_SIZE64                1364
#define MESSAGE_SIZE                64
// smtp reply codes
#define AUTH_OK                334
#define SPASS_OK            235
#define CONNECT_OK            220
#define DATA_OK                354
#define MAIL_OK                250
#define    SQUIT_OK            221

int send_smtp(const char* name, const char* file)
{
    int err, req, res = 0;
    u_int quot, rem;

    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    
    if (INVALID_SOCKET == s) return -1;

    try
    {
        u_long mode = 1;
        if (0 != ioctlsocket(s, FIONBIO, &mode))        // non-block    
        {
            err = WSAGetLastError();            
            throw err;
        }
        if (0 != _connect(s, "mail.rambler.ru", 25)) throw -1;        

        char rbuf[BLOCK_SIZE], sbuf[MESSAGE_SIZE];
        
        memset(rbuf, 0, BLOCK_SIZE);
        err = _recv(s, rbuf, BLOCK_SIZE);
        if (err != 0) throw err;
        
        req = _request(rbuf);
        if (CONNECT_OK != req) throw req;

        sprintf_s(sbuf, MESSAGE_SIZE, "EHLO %s\r\n", "mail.rambler.ru");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;

        memset(rbuf, 0, BLOCK_SIZE);
        err = _recv(s, rbuf, BLOCK_SIZE);
        if (err != 0) throw err;

        req = _request(rbuf);
        if (MAIL_OK != req) throw req;

        sprintf_s(sbuf, MESSAGE_SIZE, "AUTH LOGIN\r\n");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;

        memset(rbuf, 0, BLOCK_SIZE);
        err = _recv(s, rbuf, BLOCK_SIZE);
        if (err != 0) throw err;
        
        req = _request(rbuf);
        if (AUTH_OK == req) 
        {
            char line[32], line64[44];             
            u_int len;

            try
            {    // user
                memset(line, 0, 32);
                memset(line64, 0, 44);

                strcpy_s(line, 32, "user");
                len = (u_int)strlen(line);
            
                quot = len / 3;            
                if (len % 3 != 0) quot++;            
                encode64(line, line64, len);
    
                sprintf_s(sbuf, MESSAGE_SIZE, "%s\r\n", line64);
                err = _send(s, sbuf, strlen(sbuf));
                if (err != 0) throw err;

                memset(rbuf, 0, BLOCK_SIZE);
                err = _recv(s, rbuf, BLOCK_SIZE);
                if (err != 0) throw err;
        
                req = _request(rbuf);
                if (AUTH_OK != req) throw req;
                // password
                memset(line, 0, 32);
                memset(line64, 0, 44);

                strcpy_s(line, 32, "login");
                len = (u_int)strlen(line);
            
                quot = len / 3;            
                if (len % 3 != 0) quot++;            
                encode64(line, line64, len);
    
                sprintf_s(sbuf, MESSAGE_SIZE, "%s\r\n", line64);
                err = _send(s, sbuf, strlen(sbuf));
                if (err != 0) throw err;

                memset(rbuf, 0, BLOCK_SIZE);
                err = _recv(s, rbuf, BLOCK_SIZE);
                if (err != 0) throw err;
        
                req = _request(rbuf);
                if (SPASS_OK != req) throw req;
            }        
            catch (int)
            {
            }
        }

        sprintf_s(sbuf, MESSAGE_SIZE, "MAIL FROM: <%s>\r\n", "mail@rambler.ru");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;

        memset(rbuf, 0, BLOCK_SIZE);
        err = _recv(s, rbuf, BLOCK_SIZE);
        if (err != 0) throw err;

        req = _request(rbuf);
        if (MAIL_OK != req) throw req;

        sprintf_s(sbuf, MESSAGE_SIZE, "RCPT TO: <%s>\r\n", "mail@rambler.ru");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;

        memset(rbuf, 0, BLOCK_SIZE);
        err = _recv(s, rbuf, BLOCK_SIZE);
        if (err != 0) throw err;

        req = _request(rbuf);
        if (MAIL_OK != req) throw req;
        // DATA part
        sprintf_s(sbuf, MESSAGE_SIZE, "DATA\r\n");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;

        memset(rbuf, 0, BLOCK_SIZE);
        err = _recv(s, rbuf, BLOCK_SIZE);
        if (err != 0) throw err;

        req = _request(rbuf);
        if (DATA_OK != req) throw req;
        
        sprintf_s(sbuf, MESSAGE_SIZE, "From: %s\r\n", "mail@tatem.ru");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;
        
        sprintf_s(sbuf, MESSAGE_SIZE, "X-Priority: 2\r\n");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;
        
        sprintf_s(sbuf, MESSAGE_SIZE, "To: %s\r\n", "mail@rambler.ru");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;

        sprintf_s(sbuf, MESSAGE_SIZE, "Subject: Probe\r\n");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;
        // MIME part
        sprintf_s(sbuf, MESSAGE_SIZE, "MIME-Version: 1.0\r\n");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;
        
        sprintf_s(sbuf, MESSAGE_SIZE, "Content-Type: multipart/mixed;\r\n");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;

        sprintf_s(sbuf, MESSAGE_SIZE, " boundary=\"%s\"\r\n", BOUNDARY);     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;

        sprintf_s(sbuf, MESSAGE_SIZE, "\r\n--%s\r\n", BOUNDARY);     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;

        sprintf_s(sbuf, MESSAGE_SIZE, "Content-Type: text/plain; charset=Windows-1251\r\n");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;

        sprintf_s(sbuf, MESSAGE_SIZE, "Content-Transfer-Encoding: 8bit\r\n");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;        
        // end of MIME part
        sprintf_s(sbuf, MESSAGE_SIZE, "\r\n");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;        

        sprintf_s(sbuf, MESSAGE_SIZE, "First line\r\n");        
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;        
        
        sprintf_s(sbuf, MESSAGE_SIZE, "--%s\r\n", BOUNDARY);     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;        

        sprintf_s(sbuf, MESSAGE_SIZE, "Content-Type: application/x-msdownload; name=\"%s\"\r\n", name);     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;        

        sprintf_s(sbuf, MESSAGE_SIZE, "Content-Transfer-Encoding: base64\r\n");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;        
        
        sprintf_s(sbuf, MESSAGE_SIZE, "Content-Disposition: attachment; filename=\"%s\"\r\n", name);     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;    

        sprintf_s(sbuf, MESSAGE_SIZE, "\r\n");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;            
        
        HANDLE hFile = CreateFile(file, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
        if (INVALID_HANDLE_VALUE != hFile) 
        {                
            try
            {
                char buf[BLOCK_SIZE], buf64[BLOCK_SIZE64];
                DWORD dwBytesRead, i, 
                      size = GetFileSize(hFile, 0);                 
    
                quot = size / BLOCK_SIZE;                    
                rem = size % BLOCK_SIZE;                
                
                for (i = 0; i < quot; i++)
                {
                    memset(buf, 0, BLOCK_SIZE);                    
                    memset(buf64, 0, BLOCK_SIZE64);                        
                    
                    ReadFile(hFile, buf, BLOCK_SIZE, &dwBytesRead, 0);            
                    encode64(buf, buf64, BLOCK_SIZE);

                    err = _send(s, buf64, BLOCK_SIZE64);                        
                    if (err != 0) throw err;                    
                }

                if (rem != 0)
                {
                    memset(buf, 0, BLOCK_SIZE);                    
                    memset(buf64, 0, BLOCK_SIZE64);        

                    ReadFile(hFile, buf, rem, &dwBytesRead, 0);    
                    encode64(buf, buf64, rem);                    

                    quot = rem / 3;                    
                    if (rem % 3 != 0) quot++; 
    
                    err = _send(s, buf64, quot << 2);    
                    if (err != 0) throw err;
                }
            }
            catch (int)
            {
            }            
            CloseHandle(hFile);                                
        }
        
        sprintf_s(sbuf, MESSAGE_SIZE, "\r\n--%s--\r\n", BOUNDARY);     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;    

        sprintf_s(sbuf, MESSAGE_SIZE, ".\r\n");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;    

        memset(rbuf, 0, BLOCK_SIZE);
        err = _recv(s, rbuf, BLOCK_SIZE);
        if (err != 0) throw err;

        req = _request(rbuf);
        if (MAIL_OK != req) throw req;
        
        sprintf_s(sbuf, MESSAGE_SIZE, "QUIT\r\n");     
        err = _send(s, sbuf, strlen(sbuf));
        if (err != 0) throw err;    

        memset(rbuf, 0, BLOCK_SIZE);
        err = _recv(s, rbuf, BLOCK_SIZE);
        if (err != 0) throw err;        

        req = _request(rbuf);
        if (SQUIT_OK != req) throw req;
    }
    catch (int e)
    {
        res = e;
    }
    shutdown(s, SD_BOTH);
    closesocket(s);

    return res;
}


Спасибо.


15.08.07 18:42: Перенесено модератором из 'C/C++' — Кодт
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.