Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Не посылается письмо размером больше 6 кб


Страницы:   1 2

FFx01 ©   (2006-07-27 06:47:00) 

Пытаюсь выслать сообщение(c аттачем) на e-mail, сообщение посылается, но не больше 6 кб.  Как можно выслать сообщение больше этого кол-ва?

Вот примерная процедура посылки сообщения
///--------------------------------------------
uses winsock;
procedure mys(str: String);
var
I: Integer;
begin
for I:=1 to Length(str) do if send(sock,str[I],1,0)=SOCKET_ERROR then exit;
end;
begin
MySmtp:='87.249.30.162';
WSAStartUp(257, wsadata);
sock:=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
sin.sin_family := AF_INET;
htons(25);
sin.sin_port := htons(25);
iaddr:=inet_addr(PChar(MySmtp));
sin.sin_addr.S_addr:=iaddr;
connect(sock,sin,sizeof(sin));
Mys('HELO world'+#13+#10);
Mys('MAIL FROM: user@mail.ru'+#13+#10);
Mys('RCPT TO: sender@nxt.ru'+#13+#10);
Mys('DATA'+#13+#10);
 Mys('MIME-Version: 1.0'+#13+#10);
 Mys('To: sender@nxt.ru'+#13+#10);
 Mys('From: user@mail.ru'+#13+#10);
 Mys('Subject: hello world'+#13+#10);
 Mys('Date: [e.g Tue, 11 Dec 2002 11:10:00 -0400]'+#13+#10);
 Mys('Content-Type: application/octet-stream; name="file.txt"'+#13+#10);
 Mys('Content-Type: text/plain; charset=koi8-r Content-Transfer-Encoding: 8bit'+#13+#10);
 Mys('Content-Disposition: attachment; filename="file.txt"'+#13+#10);
 Mys(''+#13+#10);
//--------------------------------
 fName := 'text.txt';
 AssignFile(f, fName);
 Reset(f);
 {$I+}
 while not EOF(f) do
 begin
   readln(f, bufer);
   Mys(bufer+#13#10);
 end;
 CloseFile(f);
//----------------------------
 Mys('.'+#13+#10);
 Mys('QUIT'+#13+#10);
closesocket(sock);
end.


Anatoly Podgoretsky   (2006-10-30 19:49:00) [1]

> Dmitry_177  (30.10.2006 19:33)  [32]

Я не хочу твой код анализировать, вместо него можешь выложить результат для
упаковки 1, 2, 3 и 4 байт. Глазом сразу будет видно правильно сделана
упаковка или нет. Кстати обязательно надо проверить и на 0 байт. Разбиение
на 54/72 символа упаковки не касается, это ограничение транспортных каналов,
никто не мешает упаковать хоть мегабайт одной строкой.


Dmitry_177   (2006-10-30 19:33:00) [2]

Я то понимаю ))) Но а как у меня это реализовано?


Anatoly Podgoretsky   (2006-10-30 19:18:00) [3]

> Dmitry_177  (30.10.2006 17:11)  [30]

Мусор будет, если неправильно реализована функция Base64, как например у The
Bat!
Точнее не мусор, а потеря информации, например заголовок письма будет
обрезаным и при напряженной переписке будет становиться все меньше и меньше.
А с алгоритмом какие проблемы, берез из файла по 54 байта и кодируешь,
последняя строка может быть короче.


Dmitry_177   (2006-10-30 17:11:00) [4]

Что-то вроде получается ))) Строку перевожу в Base64 и для наглядности(в качестве теста) вставляю ее в Memo.. Сделал я так, если файл больше 54 байт, то считываем его по 54 байта в строку, а если нет то в одну строчку...
Как такой алгоритм? Или надо еще как-то? А еще, если файл больше 54 байт я считываю по 54 байт, а последняя строка может быть вовсе и не 54 байта, и при переводе в Base64 оставшееся место стокт может занять мусор, как это убрать это? Я дкмал размер файла поделить на 54 и последнюю строку установить размер длиной на остаток от деления и считать... Но мне кажется это все как-то муторно, наверно есть способ получше, подскажите пожалйста... Заранее спасибо.

var
 hFile: THandle;
 BytesRead: DWord;
 Str: string;
 FSize: DWord;
...

hFile := CreateFile('c:\1.txt', GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

FSize := GetFileSize(hFile, nil);

if FSize > 54 then
 begin
   SetLength(Str, 54);
     repeat
       ReadFile(hFile, Str[1], 54, BytesRead, nil);
       Memo1.Lines.Add(EncodeBase64(Str));
     until BytesRead = 0;
 end
else
 begin
   SetLength(Str, FSize);
   ReadFile(hFile, Str[1], FSize, BytesRead, nil);
   Memo1.Text := EncodeBase64(Str);
 end;

CloseHandle(hFile);


Dmitrij_K   (2006-10-30 16:55:00) [5]


> Dmitry_177

CreateFile - посмотри реализацию функции SysUtils.FileOpen()
Size - Windows.GetFileSize()
ReadFile - SysUtils.FileRead()
закрытие - CloseHandle


Anatoly Podgoretsky   (2006-10-30 16:34:00) [6]

Это ограничение по верхней странице, согласно негласному стандарту, рекомендовано в RFC, строки должны быть не более 72 символов. Но это не догма.


Dmitry_177   (2006-10-30 16:30:00) [7]

Вот функция перевода файла в строку, но она через файловый поток... Но если приложение пишется на одном API, т.е. используются модули только Windows и Messages, не хочется Classes подключать... То нужно через CreateFile и ReadFile реализовывать?


procedure LoadStringFromFile(const FileName: string):string;
var
 Stream: TStream;
 Size: Integer;
begin
 result := '';
 Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
 try
   Size := Stream.Size;
   SetString(result, nil, Size);
   Stream.Read(Pointer(result)^, Size);
 finally
   Stream.Free;
 end;
end;


Dmitry_177   (2006-10-30 16:25:00) [8]

а если файл меньше 54 байт?


Anatoly Podgoretsky   (2006-10-30 15:39:00) [9]


> Делай по 108, главное крано 4

Это не обязательно, этим должен заниматься реализатор протокола, но сколько же их кривый и именитых, например The Bat!


Anatoly Podgoretsky   (2006-10-30 15:38:00) [10]


> Почему именно по 54 байта?

54/3*4=72
А это общепринятое негласное соглашение, результат виден на любом терминале.
Можешь использовать любое другое значение, но не удивляйся, если что то, где то не пройдет. Может у реализатора жестко прописан буфер на 72 символа.


atruhin   (2006-10-30 14:29:00) [11]

> Почему именно по 54 байта?

Делай по 108, главное крано 4


Dmitry_177   (2006-10-30 13:52:00) [12]

и так пробовал, тоже самое...

ReadFile(hFile, Str[1], GetFileSize(hFile, nil), BytesRead, nil);


Dmitry_177   (2006-10-30 13:45:00) [13]

Почему именно по 54 байта?
Подскажите пожалуйста что не так? Файл присылается, но занимает 0 байт. Помогите...

var
hFile: THandle;
Str: String;
BytesRead: DWord;
...

hFile := CreateFile('c:\1.txt', GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
ReadFile(hFile, Str[1], 54, BytesRead, nil);
CloseHandle(hFile);
SMTPSendString(MailSock, EncodeBase64(Str));


Dmitry_177   (2006-10-29 23:13:00) [14]

Подскажите хотябы так правильно или нет?


Dmitry_177   (2006-10-29 18:14:00) [15]

Как его поместить в строку? Так?

var
FS: TFileStream;
...

FS.Create('c:\1.txt', fmOpenRead);
SMTPSendString(MailSock, String(FS));
FS.Free;


Anatoly Podgoretsky   (2006-10-29 18:08:00) [16]

> Ответ на сообщение [17]

Не пробовал догадаться поместить файл в строку?
Или по блочно сфайлом работать, по 54 байта?
А еще лучше написать файловый поток.


Dmitry_177   (2006-10-29 17:41:00) [17]

Я видел такую функцию:

function EncodeBase64(Value:string):string;
const Lkp64='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0 123456789+/=';
var c:byte; n:integer; Count:integer; DOut:array[0..3] of Byte;
begin
Result:=EmptyStr;
Count:=1;
while Count<=Length(Value) do
begin
c:=Ord(Value[Count]);
Inc(Count);
DOut[0]:=(c and $FC) shr 2;
DOut[1]:=(c and $03) shl 4;
if Count<=Length(Value) then
begin
c:=Ord(Value[Count]);
Inc(Count);
DOut[1]:=DOut[1]+(c and $F0) shr 4;
DOut[2]:=(c and $0F) shl 2;
if Count<=Length(Value) then
begin
c:=Ord(Value[Count]);
Inc(Count);
DOut[2]:=DOut[2]+(c and $C0) shr 6;
DOut[3]:=(c and $3F);
end
else
begin
DOut[3]:=$40;
end;
end
else
begin
DOut[2]:=$40;
DOut[3]:=$40;
end;
for n:=0 to 3 do
Result:=Result+Lkp64[DOut[n]+1];
end;
end;


и такую:

function EncodeBase64(const inStr: string): string;

 function Encode_Byte(b: Byte): char;
 const
   Base64Code: string[64] = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 begin
   Result := Base64Code[(b and $3F)+1];
 end;

var
 i: Integer;
begin
 i := 1;
 Result := '';
 while i <= Length(InStr) do
 begin
   Result := Result + Encode_Byte(Byte(inStr[i]) shr 2);
   Result := Result + Encode_Byte((Byte(inStr[i]) shl 4) or (Byte(inStr[i+1]) shr 4));
   if i+1 <= Length(inStr) then
     Result := Result + Encode_Byte((Byte(inStr[i+1]) shl 2) or (Byte(inStr[i+2]) shr 6))
   else
     Result := Result + '=';
   if i+2 <= Length(inStr) then
     Result := Result + Encode_Byte(Byte(inStr[i+2]))
   else
     Result := Result + '=';
   Inc(i, 3);
 end;
end;


Но они же только строку типа stringпереводят, а не файл... А как быть с файлом? А еще я заметил, в этих функциях, в константах, с перечислением символов, в некоторых случаях есть в конце символ <>=<> а где нету, всеже он нужен или нет?


Anatoly Podgoretsky   (2006-10-29 17:27:00) [18]

> Ответ на сообщение [15]

Различного рода процедур по преобразованию в Base64 по Сети разбросано как
грязи, и обычно Интернет компоненты уже имеют готовые функции.


Dmitry_177   (2006-10-29 17:22:00) [19]

Почитал везде так и не нашел ответа на вопрос... Всеже как мне переводить файл в Base64, считывать побайтно и переводить какнибудь или как?


Dmitry_177   (2006-10-29 01:00:00) [20]

Спасибо.. Вы очень добры...


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо