Click here to Skip to main content
6,595,854 members and growing! (19,785 online)
Email Password   helpLost your password?
General Programming » Programming Tips » General     Intermediate License: The Microsoft Public License (Ms-PL)

Send mail without specifying an SMTP server

By Nishant Sivakumar

A class derived from CSMTPConnection that queries the MX record for a target domain and uses that to send mail
VC7, VC7.1Win2K, WinXP, Win2003, Visual Studio, ATL, Dev
Posted:12 Apr 2005
Views:177,942
Bookmarked:81 times
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
38 votes for this article.
Popularity: 6.76 Rating: 4.28 out of 5
6 votes, 15.8%
1

2
2 votes, 5.3%
3
3 votes, 7.9%
4
27 votes, 71.1%
5

Overview

Quite frequently, you hear people asking how they can send an email from their applications to a specific email address without prompting the user for a relaying SMTP server. The most commonly suggested solution is to use MAPI and get a list of SMTP servers from the user's registry, but this assumes that the user has configured a MAPI compliant email client on his machine. I always reply with my solution of querying the MX record for the target domain and then SMTP-chatting to that server directly - it's easy to do, it works on any machine and it's also the fastest way to send email (minimum number of SMTP hops).

Starting with VC++ 7, ATL includes the CSMTPConnection class which lets you send mail, provided you give it an SMTP server to connect to. I derived a class (CSMTPConnection2) from CSMTPConnection which lets you pass in the target domain name directly and the class queries the MX records using the default DNS on the client machine, gets a list of SMTP servers (depending on the number of MX records returned) and connects to the first SMTP server that works okay. The only visible change is to the Connect method, and even for the Connect method, the method signature remains the same. The first parameter (an LPCTSTR) now represents the target domain name instead of the SMTP hostname. So it should be pretty easy to modify your existing code. Just change all references to CSMTPConnection in your code to CSMTPConnection2 and you are done.

Using the class

  • #include the header file for the class

    #include "smtpconnection2.h"

    The header file includes a #pragma linker directive to include Dnsapi.lib

  • Use the CSMTPConnection2 class just as you would use the CSMTPConnection class (it's assumed that CoInitialize has been called prior to invoking and using this class)

    CMimeMessage msg;
    msg.SetSender("nish@somedomain.com");
    msg.SetSenderName("Nishter");
    msg.AddRecipient("someone@vsnl.com");
    
    //Optional
    
    msg.SetSubject("Hello World");
    msg.AddText("Hmmm, this should work fine!");
    //msg.AttachFile("some file path");
    
    
    CSMTPConnection2 conn;
    //You need to specify the domain name of the recipient email address
    
    if(conn.Connect("vsnl.com"))
    {
        if( conn.SendMessage(msg) == TRUE )
            std::cout << "Mail sent successfully" << std::endl;
        conn.Disconnect();    
    }
    

Class requirements

  • You'll need VC++ 7 or above (for the ATL classes)

  • This code will run only on Windows 2000 or later (because of the DNS API that's used to query the MX record)

  • You do not need MFC (the CString that's used is shared between MFC/ATL and I specifically used CSimpleArray instead of an MFC array class)

Limitation

Note that, because the class looks up the MX record and SMTPs directly into the mail server for each domain name, you cannot use this class to send mails to multiple-domains in one go.

Source listings

Header file

/*
    Copyright(C) Nishant Sivakumar (nish#voidnish.com)
    Please maintain this copyright notice if you distribute this file
    in original or modified form.
*/

#pragma once
#include <atlsmtpconnection.h>

#include <Windns.h>


#pragma comment(lib,"Dnsapi.lib")

class CSMTPConnection2 : public CSMTPConnection
{
public:    
    BOOL Connect(LPCTSTR lpszHostDomain, DWORD dwTimeout = 10000) throw();
private:
    void _GetSMTPList(LPCTSTR lpszHostDomain, CSimpleArray<CString>& arrSMTP);
}; 

Cpp file

/*
    Copyright(C) Nishant Sivakumar (nish#voidnish.com)
    Please maintain this copyright notice if you distribute this file
    in original or modified form.
*/

#include "StdAfx.h"

#include "smtpconnection2.h"


BOOL CSMTPConnection2::Connect(LPCTSTR lpszHostDomain, 
                               DWORD dwTimeout /*= 10000*/) throw()
{
    CSimpleArray<CString> arrSMTP;
    _GetSMTPList(lpszHostDomain, arrSMTP);
    for(int i=0; i<arrSMTP.GetSize(); i++)
    {
        if(CSMTPConnection::Connect(arrSMTP[i], dwTimeout) == TRUE)
            return TRUE;
    }
    return FALSE;
}

void CSMTPConnection2::_GetSMTPList(LPCTSTR lpszHostDomain, 
                                   CSimpleArray<CString>& arrSMTP)
{
    PDNS_RECORD pRec = NULL;
    if(DnsQuery(lpszHostDomain, DNS_TYPE_MX, DNS_QUERY_STANDARD,
        NULL, &pRec, NULL) == ERROR_SUCCESS)
    {
        PDNS_RECORD pRecOrig = pRec;
        while(pRec)
        {
            if(pRec->wType == DNS_TYPE_MX)
                arrSMTP.Add(pRec->Data.MX.pNameExchange);
            pRec = pRec->pNext;
        }
        DnsRecordListFree(pRecOrig,DnsFreeRecordList);
    }
} 

Conclusion

As usual, feedback is welcome and appreciated whether it's constructive or not.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

About the Author

Nishant Sivakumar


Member
Nish is a real nice guy living in Atlanta, who has been coding since 1990, when he was 13 years old. Originally from sunny Trivandrum in India, he recently moved to Atlanta from Toronto and is a little sad that he won't be able to play in snow anymore.

Nish has been a Microsoft Visual C++ MVP since October, 2002 - awfully nice of Microsoft, he thinks. He maintains an MVP tips and tricks web site - www.voidnish.com where you can find a consolidated list of his articles, writings and ideas on VC++, MFC, .NET and C++/CLI. Oh, and you might want to check out his blog on C++/CLI, MFC, .NET and a lot of other stuff - blog.voidnish.com

Nish loves reading Science Fiction, P G Wodehouse and Agatha Christie, and also fancies himself to be a decent writer of sorts. He has authored a romantic comedy Summer Love and Some more Cricket as well as a programming book – Extending MFC applications with the .NET Framework.

Nish's latest book C++/CLI in Action published by Manning Publications is now available for purchase. You can read more about the book on his blog.

Despite his wife's attempts to get him into cooking, his best effort so far has been a badly done omelette. Some day, he hopes to be a good cook, and to cook a tasty dinner for his wife.
Location: United States United States

Other popular Programming Tips articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 25 of 130 (Total in Forum: 130) (Refresh)FirstPrevNext
Generaldebug assertion failed notifications Pinmembereugene pinsky9:00 17 Aug '09  
GeneralSend without smtp server [modified] PinmemberDipak V Bava11:02 28 Feb '09  
GeneralRe: Send without smtp server PinmemberElmue8:11 24 Apr '09  
GeneralRe: Send without smtp server PinmemberDipak V Bava8:32 24 Apr '09  
GeneralWhat about VC++ 2008? PinmemberMember 313605623:55 6 Feb '09  
GeneralRe: What about VC++ 2008? PinmemberDave Calkins4:45 28 Feb '09  
GeneralUseful article Pinmemberom13:33 7 Jan '09  
GeneralCOM and ActiveX implementation? Pinmemberdaluu20:40 1 Nov '08  
General.NET alternative Pinmemberdaluu21:25 3 Oct '08  
GeneralQuite useless code! PinmemberElmue12:48 17 Jul '08  
Generalatlsmtpconnection.h PinmembertheCPkid5:06 28 Jun '08  
GeneralProps to Nish Pinmemberbvaghani17:31 26 Jan '08  
Generalrename Connect to ConnectDomain PinmemberHerbert Yu11:29 29 Nov '07  
GeneralRe: rename Connect to ConnectDomain PinmemberYogesh P. Dhakad4:03 13 Jan '08  
GeneralNot working with all providers [modified] PinmemberManthis0:46 19 Nov '07  
GeneralWorks for me on hotmail.com PinmemberHerbert Yu10:45 29 Nov '07  
GeneralRe: Not working with all providers PinmemberMunahid23:47 28 Sep '09  
QuestionMail subject not working PinmemberManthis23:52 18 Nov '07  
AnswerRe: Mail subject not working PinmemberHerbert Yu10:35 29 Nov '07  
GeneralSecurity PinmemberMike Booker16:57 18 Sep '07  
GeneralRe: Security PinmemberHerbert Yu10:37 29 Nov '07  
GeneralVirus detection Pinmembernat2kus11:38 21 May '07  
GeneralRe: Virus detection [modified] Pinmembernat2kus11:44 21 May '07  
GeneralRe: Virus detection PinmemberHerbert Yu9:13 28 Nov '07  
QuestionHTML msg PinmemberRisKhan1:49 9 Apr '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 12 Apr 2005
Editor: Nishant Sivakumar
Copyright 2005 by Nishant Sivakumar
Everything else Copyright © CodeProject, 1999-2009
Web16 | Advertise on the Code Project