Написал 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++' — Кодт