How to send a mail message using Indy's smtp server component? - delphi

Since the demo given in http://www.indyproject.org/Sockets/Demos/index.EN.aspx only saves the received stream to a file, I don't know how to effectevely send that stream as a mail.
Could anyone teach me how to do this or to point me some more complete example?

Here's a complete example on how to send an email:
VAR SMTP : TIdSMTP;
VAR MSG : TIdMSG;
.
.
MSG:=TIdMSG.Create(NIL);
TRY
WITH MSG.Recipients.Add DO BEGIN
Name:='<Name of recipient>';
Address:='<Email address of recipient>'
END;
MSG.BccList.Add.Address:='<Email address of Blind Copy recipient>';
MSG.From.Name:='<Name of sender>';
MSG.From.Address:='<Email address of sender>';
MSG.Body.Text:='<Message Body>';
MSG.Subject:='<Subject of message>';
SMTP:=TIdSMTP.Create(NIL);
TRY
SMTP.Host:='x.x.x.x'; // IP Address of SMTP server
SMTP.Port:=25; // Port address of SMTP service (usually 25)
SMTP.Connect;
TRY
SMTP.Send(MSG)
FINALLY
SMTP.Disconnect
END
FINALLY
SMTP.Free
END
FINALLY
MSG.Free
END;
.
.
(I know that WITH is frowned upon, but I generally use it in instances like this where there's no doubt as to what is going on, and where there's no (or just an infinitesimal) chance of ambiguity)

A SMTP server component can't send mail - it can only receive it. You need a SMTP client component (TidSMTP) to send mail. A mail server when it sends mail acts like an SMTP client.

Related

How to connect to a local idIRCServer

Well I have create a project which uses idIRCClient to connect to an IRC server and get responses from the server using that code
with ircClient do
if (edt1.text<>'') and (edt2.text<>'') and (edt3.text<>'') then
try
Host:=edt1.Text;
port:=StrToIntDef(edt2.Text,6667);
Nickname:=edt3.Text;
Username:=edt4.Text;
Connect;
except
if not Connected then
MessageDlg('Error',mtError,[],0);
end
else
MessageDlg('fill all the fields',mtInformation,[],0);
well when I use a host like "ix1.undernet.org" with port 6667 I get responses and a welcome message and I can send c2c private messages , whereas when I create an other module which contains idIRCServer and make it active then connect to it using host='localhost' and port=6667 , I get connected but I don't get any response from the server nor a welcome message even if it is set withing the Greeting Property
Thanks in advance

Simple XMPP client using Synapse

I'm trying to build my simple xmpp client to avoid using 3rd party components cause I need only some very basic functions like new account registration and sending messages (e.g. a basic jabber bot).
I'm not completely new to Delphi and even to Synapse (was using it's HTTPsend class before), but I am relatively new at sending data through TCP/IP socket and am stuck with some problems.
Basically, I've read about XMPP protocol specs and found out it is relatively simple to deal with, because it uses XML and is well-explained. I started with capturing some packets from a real client communicated with XMPP server. The very first task I decided to implement was new account creation.
Here is what the client sent to the server:
http://notepad.cc/faxije16
These are the initial packets.
Now comes the problem.
I wrote the following function to maintain sending xml to the server and read the response
function sndq(const query: string;sock: ttcpblocksocket): string;
var c: string;
i: integer;
begin
result:='';
sock.SendString(query);
c:='';
for i := 0 to 5000 do begin
c:=Sock.RecvBufferStr(1, 2500);
result := result + c;
end;// for i
end;:
First of all, I feel very wrong about doing that for...doing thing, but I tried using sock.waitingdata and waitingdataex, but it somehow returns wrong value (less then actual response size).
But the bigger problem is that I can only receive the first packet. So Here is the code I've written:
var sock: ttcpblocksocket;
begin
sock:=ttcpblocksocket.Create;
sock.Connect('exploit.im','5222');
writeln(sndq('<stream:stream to="exploit.im" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" xml:lang="ru" version="1.0" />',sock)); // goes well as I get that same initial packet as the client
writeln('----------');
writeln(sndq('<iq type="get" id="qip_0"><query xmlns="jabber:iq:register" /></iq>',sock)); // шлем запрос точно как у Квипа // prints empty line
readln; end.
I hope that I've explained my problem well.
Probably these questions are already answered but I wasn't able to find any way around, so please point out what do I have to correct in the code above (about determining actual response size and about being able to receive only a packet).
Thanks.

Delphi XE2 DataSnap Server - Log client connection user/properties

I'm building an XE2 DataSnap server which will serve connections from REST clients. My DSServerClass LifeCycle property is set to 'Invocation'. What I want to do is to log the details of all client connections to the server, including the following details : username, IP address, protocol, application name. I can currently get these details using the following events :
DSAuthenticationManager - UserAuthenticate() : username, protocol (using the standard parameters passed in)
DSServer - Connect() : protocol, IP address, application name (using DSConnectEventObject.ChannelInfo.ClientInfo)
What I want to do is just log once for all details, but it seems I can't get all the details I need in one event. I tried using a shared private variable in the class but as expected this gave inconsistent results - the wrong IP address against the wrong username. Is there another way to achieve what I want?
Jonathan
procedure TServerContainer1.DSServer1Connect(DSConnectEventObject: TDSConnectEventObject);
begin
Form1.Memo1.Lines.Add(Format('Conn->UserName=%s, Password=%s', [
DSConnectEventObject.ConnectProperties[TDBXPropertyNames.UserName],
DSConnectEventObject.ConnectProperties[TDBXPropertyNames.Password]
]));
// 取 Client 端的IP 和 Port
Form1.Memo1.Lines.Add('IP =' + DSConnectEventObject.ChannelInfo.ClientInfo.IpAddress + ':'
+ DSConnectEventObject.ChannelInfo.ClientInfo.ClientPort);
end;
You can use TDSServer.OnConnect event (which is called after TDSAuthenticationManager.OnUserAuthenticate). There you have access to ChannelInfo.ClientInfo as you've discovered and also ConnectProperties from which you can read property values like this:
Scheme := ConnectProperties.Values[TDBXPropertyNames.DSAuthenticationScheme];
UserName := ConnectProperties.Values[TDBXPropertyNames.DSAuthenticationUser];
Password := ConnectProperties.Values[TDBXPropertyNames.DSAuthenticationPassword];

Send an email with attachment Client Agnostic

I currently have an application written that generates pdf vouchers and emails to their perspective recipients. However the function I use is client dependent (MS Outlook) and I would really like to make this email client agnostic as we have many customers and not all of them use Outlook.
I have looked at a few options but can't really find anything in searching that seems to solve my problem.
Does anyone know a good way to send email using the customers smtp connection regardless of the client and send an attachment with it without calling the client directly to do it?
Or you can use the Synapse library, for sending a mail using SMTP, ideally in its newest snapshot.
Here is the code which should send the mail with attached c:\voucher.pdf file from sender#from.com to recipient#to.com to the smtp.server.com with login login and password password. About the rest of the functions from the TMimeMess class I would refer you directly to the reference.
I hope this will work because I've simplified and localized much more complicated code I'm using and I can't verify it nor compile. If not, let's downvote it :)
uses
SMTPSend, MIMEPart, MIMEMess;
procedure TForm.SendEmailClick(Sender: TObject);
var
MIMEText: TStrings;
MIMEPart: TMimePart;
MIMEMessage: TMimeMess;
begin
MIMEText := TStringList.Create;
MIMEText.Add('Hello,');
MIMEText.Add('here is the text of your e-mail message,');
MIMEText.Add('if you want the HTML format, use AddPartHTML');
MIMEText.Add('or e.g. AddPartHTMLFromFile if you have your');
MIMEText.Add('HTML message content in a file.');
MIMEMessage := TMimeMess.Create;
with MIMEMessage do
try
Header.Date := Now;
Header.From := 'sender#from.com';
Header.ToList.Clear;
Header.ToList.Add('recipient#to.com');
Header.CcList.Clear;
Header.Subject := 'E-mail subject';
Header.XMailer := 'My mail client name';
MIMEPart := AddPartMultipart('mixed', nil);
AddPartText(MIMEText, MIMEPart);
AddPartBinaryFromFile('c:\voucher.pdf', MIMEPart);
EncodeMessage;
if SendToRaw(Header.From, // e-mail sender
Header.ToList.CommaText, // comma delimited recipient list
'smtp.server.com', // SMTP server
Lines, // MIME message data
'login', // server authentication
'password') // server authentication
then
ShowMessage('E-mail has been successfuly sent :)')
else
ShowMessage('E-mail sending failed :(');
finally
Free;
MIMEText.Free;
end;
end;
Update:
According to nice comment from Downvoter step into the light (man, change your nick please, it's not cool anymore :), would be really bad if you will send the list of all recipients to everyone. With synapse you cannot add BCCs to the message header; there's no Header.BCCList property in MIMEMessage.
Instead you can directly modify the data before sending them.
// First, you will remove the line where you are adding a recipient to the list
Header.ToList.Add('recipient#to.com');
// the rest between you can keep as it is and after the message encoding
EncodeMessage;
// and before sending the mail you'll insert the line with BCCs
Lines.Insert(1, 'Bcc: jane#invisiblecustomer.com, lisa#invisiblecustomer.com');
if SendToRaw ...
You could use Indy as your SMTP client, independent of the system default e-mail client. Here's a basic demo of sending e-mails without attachments, and there are detailed articles here and here about sending HTML or plain-text e-mails and with or without attachments.
If you want to integrate with the existent email client (e.g. see the sent messages in the sent, sent items, etc. folder of the email client), you could use Simple MAPI. The headers are translated in the Mapi unit in Delphi (at least in D2007).
But be careful to check if the actual client supports Simple MAPI.

Any way to authenticate with a websense server from delphi?

We use a websense internet filter at my workplace. I have an application that tries to retrieve information from the internet.
On my client machine, I have to authenticate with websense manually (i.e., open firefox and give my username / password) or I'll get an error in my application when it tries to do the download.
The error message is:
HTTP/1.0 302 Moved.
Does anyone know of a way to authenticate with websense from code? Examples in any language are welcome- I am using Delphi and Indy's TIdHTTP component.
Answering my own question; this is what worked for me.
The custom user agent string is only required if you want the authentication to let MSN / Live messenger get through, as described under "notes" at the end of this article.
In a command line application:
uses
... IdHTTP ...;
...
var
httpGetter: TIdHTTP;
...
httpGetter.Request.Username := username;
httpGetter.Request.Password := password;
httpGetter.HandleRedirects := True;
httpGetter.Request.BasicAuthentication := True;
//custom useragent required to let live messenger work
httpGetter.Request.UserAgent := 'MSN Explorer/9.0 (MSN 8.0; TmstmpExt)';
httpGetter.Get(url,MS);
...
I would try HTTP authentication
http://en.wikipedia.org/wiki/Basic_access_authentication

Resources