Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

[C/C++] Sending Email via ATL under Windows

Adam Zaius
Deus
Join date: 9 Jan 2004
Posts: 1,483
03-30-2004 03:45
Since there was a rather profound lack of documentation on sending email via a SMTP server via google (that is reliable or not bloated to heck), I'd thought Id post what I finally got working reliably.

This is Win32 only (relies on ATL), however if you are running under *nix, then you can just use system() to call sendto or sendmail manually, which is IMHO far easier.

This should help with anyone programming 1.3 interfaces to SL. (like my winamp plugin for example). Please however remember that at the moment, the ID for an attached object appears to change each time you teleport, so you will want to include an easy way to change the id from within your app, or use a POP3 interface to retrieve the ID manually.

This function has been tested under Windows 2K proffessional, Win2K server & Win2K3 Server, however I am unsure if CMimeMessage/CSMTPConnection is implemented in the Win9X series.

The main function
CODE
void send_email(char* message, char* to, char* subject, char* smtp_server,char* from_address, char* from_name)
{
CMimeMessage msg;
msg.SetSender(from_address);
msg.SetSenderName(from_name);
msg.AddRecipient(to,"Object");
msg.SetSubject(subject);
msg.AddText(message);
CSMTPConnection connection;
connection.Connect(smtp_server);
connection.SendMessage(msg);
Sleep(1000); // Sleep so an infinite loop wont cause a large spam attack. Remove if you know what your doing.
}


Precompiled Header (usually StdAfx.h)
CODE
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#if !defined(AFX_STDAFX_H__CFF738C2_CBB7_11D4_AB00_0010A4EC0A5C__INCLUDED_)
#define AFX_STDAFX_H__CFF738C2_CBB7_11D4_AB00_0010A4EC0A5C__INCLUDED_

#if _MSC_VER < 1000
#pragma once
#endif // _MSC_VER > 1000

#define WIN32_LEAN_AND_MEAN 0 // Exclude rarely-used stuff from Windows headers
#define EXTRA_LEAN 0 // Exclude more crap

#include <stdio.h>
#include <windows.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlisapi.h>
#include <atlstencil.h>
#include <atlutil.h>
#include <atlsmtpconnection.h>
// TODO: reference additional headers your program requires here

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_STDAFX_H__CFF738C2_CBB7_11D4_AB00_0010A4EC0A5C__INCLUDED_)


Example use
CODE
#include "StdAfx.h"

void send_email(char* message, char* to, char* subject, char* smtp_server,char* from_address, char* from_name)
{
CMimeMessage msg;
msg.SetSender(from_address);
msg.SetSenderName(from_name);
msg.AddRecipient(to,"Object");
msg.SetSubject(subject);
msg.AddText(message);
CSMTPConnection connection;
connection.Connect(smtp_server);
connection.SendMessage(msg);
Sleep(1000); // Sleep so an infinite loop wont cause a large spam attack. Remove if you know what your doing.
}

int main() {
send_email("Hello World", "hello@world.com", "Hello!", "mail.xyz.com","my_email_address@email.com","Me");
return 0;
}
Huns Valen
Don't PM me here.
Join date: 3 May 2003
Posts: 2,749
04-06-2004 07:38
If you want to do it yourself, this is the SMTP protocol:

Open a connection to the mail server on port 25.
Send 'helo (some string, it doesn't matter, no spaces though)'
Mail server says something like '220 duh bluh v. 5'
Send 'mail from [email]you@address.com[/email]'
Mail server says '250 Ok'
Send 'rcpt to [email]friend@someISP.com[/email]'
Mail server says '250 Ok'
Send 'data'
Mail server waits for you to start typing. Put headers first, i.e. 'Subject: Get r1ch quick fqdnz', 'x-some-header-value: duh bluh', etc. After the headers type your message. It's all being sent as one glob of text, the e-mail reader on the other end is what decides where the headers end and the body begins.

When you are done, send a period on a line by itself, wait a sec, then close the socket.

For example...

telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 zzz.com ESMTP
helo whatever
250 zzz.com
mail from: [email]zzz@zzz.com[/email]
250 Ok
rcpt to: [email]zzz@zzz.com[/email]
250 Ok
data
354 End data with .
Subject: Test message
The above line will show up in your e-mail client as the subject. This line and everything below will show up in the body.
End with a period by itself at the beginning of a line.
.
^]
telnet> <Ctrl+D>Connection closed.
Bob Brightwillow
Technologist
Join date: 7 Feb 2003
Posts: 110
04-07-2004 23:14
From: someone
Originally posted by Huns Valen
When you are done, send a period on a line by itself, wait a sec, then close the socket.

Actually, you'll want to issue the QUIT command and let the server disconnect. This way you'll also be sure to see the server's response to the email you tried to send through it.

For the full story on how to speak SMTP, please refer to RFC 2821.