Lee, I decided it was high time that I get familiar with emailing under Synapse, so I took a look at what's available (in demo code) for binary attachments---for those of us not really wanting (or able) to slug through the SMTP RFCs just now... (someone's just gonna hafta tell me to go RTFM! <g>) --- and found some helpful and some not-so-helpful things.
Since no one else answered the main "email with binary attachment" question yet... Here's a very slightly modified simplistic demo routine I found at http://www.delphil.szm.sk/prispevky/Call%20Stack%20v%20Runtime%20106398.htm It would need some significant modifications for a number of things, like sending multiple attachments, but it seems to nicely demonstrate the basic requirements. /////////////////// function SendEmail2(Afrom, Ato, Asubject, ASMTPHost, AUserName, APassWord, AFileName: string; Atext: TStringList): boolean; var m : TMimemess; MimeBody : TMimePart; begin m := TMimemess.create; try if AFileName <> '' then begin MimeBody := M.AddPartMultiPart('mixed', nil); m.AddPartText(AText, MimeBody); m.AddPartBinaryFromFile(AFileName, MimeBody); end else m.AddPartText(AText, nil); m.header.from := AFrom; //'"Jan ?izek" <[EMAIL PROTECTED]>'; m.header.tolist.add(ATo); //'[EMAIL PROTECTED]'); m.header.subject := Asubject; // 'sislat zlu?oueky kuo Z?S Ii'; m.EncodeMessage; Result := SendToRaw(AFrom, ATo, ASMTPhost, m.lines, AUserName, APassWord); finally m.free; end; end; /////////////////// The first VERY INTERESTING thing about this AND all the other test routines I created, is that they *always* fail UNLESS I make some call to TTCPBlockSocket.ResolveNameToIP() before... and then it always succeeds. I've spent some time looking for initialization code that I should be calling elsewhere (???) but I can't find any. I'd be quite grateful for any pointers on what I'm missing, or if it's a library bug... I've come across initialization issues before, but was able to resolve them. I'm not sure what's going on here. The call to GetHostByName() in synsock.ResolveNameToIP fails with error 1060 unless TTCPBlockSocket.ResolveNameToIP() was previously called... Interesting... ----------------------- While looking through some of the code I also notice some very strange things in the MIMEPART unit in the following routine: function GenerateBoundary: string; var x, y: Integer; begin y := GetTick; x := y; while TickDelta(y, x) = 0 do begin Sleep(1); x := GetTick; end; Randomize; y := Random(MaxInt); Result := IntToHex(x, 8) + '_' + IntToHex(y, 8) + '_Synapse_boundary'; end; Maybe this is a secret weapon to slow down spammers' output... <g>, but it's really a very improper use of Randomize (that can affect the main/calling program's use of random numbers...), and then the whole GetTick and sleep() loop is trying to reduce the problems introduced by calling Randomize. Randomize is supposed to bring entropy into the pseudo random number generator, but the Delphi/Borland one (like lots of others) uses the system clock which is a VERY poor source of entropy to begin with, and worse if called repeatedly. If a developer is aware of these issues, this will become immediately obvious; if not, it will require some research and study. You could also trust the advice of the Delphi Help entry where it says: "Do not combine the call to Randomize in a loop with calls to the Random function. Typically, Randomize is called only once, before all calls to Random." In fact, as with quite a few other libraries, there are several (few) calls to Randomize in Synapse. They should all be removed; this should really only be under the calling program's control--- or, at most, called once in a unit's initialization section. Repeatedly calling randomize actually REDUCES the randomness of random() output. (That's part of one way that some online gambling houses were hacked a few years ago.) And the other code in this routine dramatically slows everything down. 5000 calls to the GenerateBoundary() routine alone (never mind other email/mimemess... code) will take about 50 seconds! (I was guesstimating it would take 5 seconds with the 1 ms. sleep; haven't figured out why it's taking 50.) The following one-line replacement routine doubles the effective random number range output. [The internals of the random functions actually treat the seed and "integer" parameters as LongWord/DWORDs. So submitting -1 (or an appropriately cast DWORD...) is like submitting 4,294,967,296, which is 2 * maxint.] It's also likely to execute 5000 times on your computer in less than 10 milliseconds <g>... function xGenerateBoundary: string; begin Result := IntToHex(Random(-1), 8) + '_' + IntToHex(Random(-1), 8) + '_Synapse_boundary'; end; ------------------------------------------------------------------------- This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone _______________________________________________ synalist-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/synalist-public
