Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

CFastSmtp - Fast and easy SMTP class...

0.00/5 (No votes)
4 Sep 2002 1  
Fast and simple win32 SMTP class with handy local ip/name funtions

Introduction

zSmtp v1.1

Win32 SMTP Wrapper with handy local ip and hostname functions.

Notes

A real basic SMTP wrapper. I tried to find one, but I couldn't - so here is another one. It is fast and straight forward - just instantiate the class with a SMTP server and then set the sender email property and message body. The rest of the settings are pretty much optional. There are also a couple of nice utility functions for getting your local hostname and local ip address.

We hope this code helps you out!

To Do

  • UUEncode/Decode
  • Attachments

Usage

CFastSmtp mail;

if (mail.ConnectServer("SERVER")) {
    mail.SetSenderName("Sender's Name");
    mail.SetSenderEmail("senders@address.com");
    mail.SetSubject("CFastSmtp v1.1 Release");

    mail.AddRecipient("test@test.com");
    mail.AddCCRecipient("test@test.com");
    mail.AddBCCRecipient("test@test.com");

    mail.SetMessageBody("Here is another test of CFastSmtp SMTP class!");
    
    if (mail.GetConnectStatus()) {        
        printf(mail.Send() ? "Send was a success!" : "Send failed!");
        mail.Disconnect();                    
    }
}   

Source Code

Here is the source (FastSmtp.cpp):

//********************************************************************

/*
  Fast & Simple SMTP Class

  Author:
    christopher w. backen <immortal@cox.net>    
  Purpose:
    Simple smtp class with handy local ip and hostname functions
  ToDo:
    Attachments & UUEncode/Decode
*/
//********************************************************************

//*** Change History

//*** DEVELOPER             DATE        MODIFICATION

//*** 

//*** christopher w. backen 09.05.2002    Misc. updates and corrections

//*** christopher w. backen    08.28.2001    Bug fixes & code changes

//*** christopher w. backen    04.12.2001    Release

//***

//********************************************************************




#include "stdafx.h"

#include "FastSmtp.h"


//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////


CFastSmtp::CFastSmtp()
{
    // Initialize variables

    bCon            = false;

    m_pcFromEmail    = NULL;
    m_pcFromName    = NULL;
    m_pcSubject        = NULL;
    m_pcMsgBody        = NULL;
    m_pcXMailer        = NULL;
    m_pcReplyTo        = NULL;
    m_pcIPAddr        = NULL;

    // Initialize WinSock

    WORD wVer    = MAKEWORD(2,2);    
    if (WSAStartup(wVer,&wsaData) != NO_ERROR) {
        printf("WSAStartup %d\r\n", WSAGetLastError());        
        throw; 
    }
    if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) {
        printf("Can't find a useable WinSock DLL\r\n");
        WSACleanup();
        throw; 
    }    
}

CFastSmtp::~CFastSmtp()
{
    // Free recipient lists

    for (unsigned int n = 0; n < Recipients.size(); n++)
        delete Recipients[n];
    for (unsigned int n = 0; n < CCRecipients.size(); n++)
        delete CCRecipients[n];
    for (unsigned int n = 0; n < BCCRecipients.size(); n++)
        delete BCCRecipients[n];

    // Free variables

    if (m_pcFromEmail)
        delete m_pcFromEmail;
    if (m_pcFromName)
        delete m_pcFromName;
    if (m_pcSubject)
        delete m_pcSubject;
    if (m_pcMsgBody)
        delete m_pcMsgBody;
    if (m_pcXMailer)
        delete m_pcXMailer;
    if (m_pcReplyTo)
        delete m_pcReplyTo;

    // Close connection

    if (bCon)
        Disconnect();

    // Cleanup

    WSACleanup();
}

bool CFastSmtp::AddRecipient(const char email[], const char name[])
{
    assert(email);

    int s=strlen(email);
    if (s==0)
        return false;

    CRecipient *pRec = new CRecipient();

    char *pcBuf = new char[s+strlen(name)+4];
     sprintf(pcBuf,"%s<%s>",name,email);    
     pRec->SetEmail(pcBuf);
     Recipients.insert(Recipients.end(), pRec);
    delete pcBuf;

    return (true);    
}

bool CFastSmtp::AddCCRecipient(const char email[], const char name[])
{
    assert(email);

    int s=strlen(email);
    if (s==0)
        return false;

    CRecipient *pRec = new CRecipient();    

    char *pcBuf = new char[s+strlen(name)+4];
     sprintf(pcBuf,"%s<%s>",name,email);    
     pRec->SetEmail(pcBuf);
     CCRecipients.insert(CCRecipients.end(), pRec);
    delete pcBuf;

    return (true);
}

bool CFastSmtp::AddBCCRecipient(const char email[], const char name[])
{
    assert(email);

    int s=strlen(email);
    if (s==0)
        return false;

    CRecipient *pRec = new CRecipient();

    char *pcBuf = new char[s+strlen(name)+4];
     sprintf(pcBuf,"%s<%s>",name,email);    
     pRec->SetEmail(pcBuf);
     BCCRecipients.insert(BCCRecipients.end(), pRec);
    delete pcBuf;    
    
    return (true);
}

bool CFastSmtp::Disconnect()
{
    if (!bCon) {
        printf("Not connected to server!\r\n");
        return (false);
    }

    BYTE        sReceiveBuffer[4096];
    int            iLength = 0;
    int            iEnd = 0;

    if (send(hSocket, (LPSTR)"QUIT\r\n", strlen("QUIT\r\n"),
             NO_FLAGS) == SOCKET_ERROR) {
        printf("Socket send error: %d\r\n", WSAGetLastError());    
        return (false);
    }
    iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd, 
                   NO_FLAGS);
    iEnd += iLength;
    sReceiveBuffer[iEnd] = '\0';

    bCon=false;    

    hSocket=NULL;

    return (true);
}

bool CFastSmtp::Send()
{
// verify sender email

    if (m_pcFromEmail == NULL) {
        printf("Please specifiy a sender email address\r\n");
        return (false);
    }

    BYTE        sReceiveBuffer[4096];
    int            iLength = 0;
    int            iEnd = 0;
    char        buf[4096];
// get proper header

    char* msgHeader = _formatHeader();

    if (msgHeader == NULL) {
        delete [] msgHeader;
        printf("Failed to format message header\r\n");
        return (false);
    }
// start

    strcpy(buf, "MAIL FROM: <");
    strcat(buf, m_pcFromEmail);
    strcat(buf, ">\r\n");
    if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) {
        printf("Socket send error: %d\r\n", WSAGetLastError());    
        return (false);
    }
    iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd, 
                   NO_FLAGS);
    iEnd += iLength;
    sReceiveBuffer[iEnd] = '\0';
// create message receipts

    char *token;
    for(unsigned int i=0;i<Recipients.size();i++) {
        token = strtok(Recipients.at(i)->GetEmail(),"<");
        token = strtok(NULL,"<");    
        if (token == NULL) 
            token = strtok(Recipients.at(i)->GetEmail(),"<");
        strcpy(buf, "RCPT TO: <");
        strcat(buf, token);
        strcat(buf, "\r\n");
        if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) {
            printf("Socket send error: %d\r\n", WSAGetLastError());    
            return (false);
        }
        iLength = recv(hSocket, 
                      (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd, 
                       NO_FLAGS);
        iEnd += iLength;
        sReceiveBuffer[iEnd] = '\0';
    }
    for(unsigned int i=0;i<CCRecipients.size();i++) {
        token = strtok(CCRecipients.at(i)->GetEmail(),"<");
        token = strtok(NULL,"<");
        if (token == NULL) 
            token = strtok(Recipients.at(i)->GetEmail(),"<");
        strcpy(buf, "RCPT TO: <");
        strcat(buf, token);
        strcat(buf, "\r\n");
        if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) {
            printf("Socket send error: %d\r\n", WSAGetLastError());    
            return (false);
        }
        iLength = recv(hSocket, 
                       (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd,
                        NO_FLAGS);
        iEnd += iLength;
        sReceiveBuffer[iEnd] = '\0';
    }
    for(unsigned int i=0;i<BCCRecipients.size();i++) {
        token = strtok(BCCRecipients.at(i)->GetEmail(),"<");
        token = strtok(NULL,"<");
        if (token == NULL) 
            token = strtok(Recipients.at(i)->GetEmail(),"<");
        strcpy(buf, "RCPT TO: <");
        strcat(buf, token);
        strcat(buf, "\r\n");
        if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) {
            printf("Socket send error: %d\r\n", WSAGetLastError());    
            return (false);
        }
        iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd,
                       sizeof(sReceiveBuffer)-iEnd, 
                       NO_FLAGS);
        iEnd += iLength;
        sReceiveBuffer[iEnd] = '\0';
    }
// init data

    if (send(hSocket, (LPSTR)"DATA\r\n", strlen("DATA\r\n"), NO_FLAGS) == SOCKET_ERROR) {
        printf("Socket send error: %d\r\n", WSAGetLastError());    
        return (false);
    }
    iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd,
                   NO_FLAGS);
    iEnd += iLength;
    sReceiveBuffer[iEnd] = '\0';
// send header    

    if (send(hSocket, 
             (LPSTR)msgHeader, strlen(msgHeader), NO_FLAGS) == SOCKET_ERROR) {
        printf("Socket send error: %d\r\n", WSAGetLastError());    
        delete [] msgHeader;
        return (false);
    }
// send body    

    if (send(hSocket, 
             (LPSTR)m_pcMsgBody, strlen(m_pcMsgBody), NO_FLAGS) == SOCKET_ERROR) {
        printf("Socket send error: %d\r\n", WSAGetLastError());    
        return (false);
    }
// signal end    

    if (send(hSocket,
            (LPSTR)"\r\n.\r\n", strlen("\r\n.\r\n"), NO_FLAGS) == SOCKET_ERROR) {
        printf("Socket send error: %d\r\n", WSAGetLastError());    
        return (false);
    }
    iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd,
                   NO_FLAGS);
    iEnd += iLength;
    sReceiveBuffer[iEnd] = '\0';
    delete [] msgHeader;
    return (true);

}

bool CFastSmtp::ConnectServer(const char server[], const unsigned short port)
{
    assert(server);

    if (bCon)
        Disconnect();
    bCon=false;
    hSocket = INVALID_SOCKET;

    hSocket = _connectServerSocket(server, port);    
    if (hSocket != INVALID_SOCKET) {        
        BYTE        sReceiveBuffer[4096];
        int            iLength = 0;
        int            iEnd = 0;
        char        buf[4096];
      
        strcpy(buf, "HELO ");
        strcat(buf, server);
        strcat(buf, "\r\n");
        if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) {
            printf("Socket send error: %d\r\n", WSAGetLastError());    
            return (false);
        }
        iLength = recv(hSocket, 
                       (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd, 
                        NO_FLAGS);
        iEnd += iLength;
        sReceiveBuffer[iEnd] = '\0';
    } else {
        printf("Invalid socket\r\n");
        return (false);
    }

    bCon=true;
    return (true);
}

SOCKET CFastSmtp::_connectServerSocket(const char server[],
                                       const unsigned short port)
{
    int                nConnect;
    short            nProtocolPort;
    LPHOSTENT        lpHostEnt;
    LPSERVENT        lpServEnt;
    SOCKADDR_IN        sockAddr;        

    SOCKET            hServerSocket = INVALID_SOCKET;
     
    lpHostEnt = gethostbyname(server);
    if (lpHostEnt) {        
        hServerSocket = socket(PF_INET, SOCK_STREAM,DEFAULT_PROTOCOL);
        if (hServerSocket != INVALID_SOCKET) {
            if (port != NULL) {
                nProtocolPort = port;
            }else{
                lpServEnt = getservbyname("mail", DEFAULT_PROTOCOL);
                if (lpServEnt == NULL) 
                    nProtocolPort = htons(IPPORT_SMTP); 
                else 
                    nProtocolPort = lpServEnt->s_port;
            }
            sockAddr.sin_family = AF_INET;
            sockAddr.sin_port = nProtocolPort;
            sockAddr.sin_addr = *((LPIN_ADDR)*lpHostEnt->h_addr_list);
            nConnect = connect(hServerSocket, (PSOCKADDR)&sockAddr, 
                               sizeof(sockAddr));
            if(nConnect) 
                hServerSocket = INVALID_SOCKET;
        } else {
            printf("Invalid socket\r\n");
            throw;
        }
    }
    return(hServerSocket);
}

char* CFastSmtp::_formatHeader()
{
// check for at least one recipient

    if(Recipients.size() <= 0 )    {
        printf("Please add a message recipient!\r\n");
        return NULL;
    }
    int s=0;
    char *msgHeader = new char[16385];
    //char to[1024];

    for (unsigned int i=s=0;i<Recipients.size();i++) {        
        s+=strlen(Recipients.at(i)->GetEmail())+1;
    } if (s==0) s=1; char *to = new char[s];
    //char cc[1024];

    for (i=s=0;i<CCRecipients.size();i++) {        
        s+=strlen(CCRecipients.at(i)->GetEmail())+1;
    } if (s==0) s=1; char *cc = new char[s];
    //char bcc[1024];

    for (i=s=0;i<BCCRecipients.size();i++) {        
        s+=strlen(BCCRecipients.at(i)->GetEmail())+1;
    } if (s==0) s=1; char *bcc = new char[s];

    TCHAR szDate[500];
    TCHAR sztTime[500];

// create the recipient string, cc string, and bcc string

    to[0] = '\0';        
    for (i=0;i<Recipients.size();i++) {        
        i > 0 ? strcat(to,","):strcat(to,"");
        strcat(to,Recipients.at(i)->GetEmail());
    }

    cc[0] = '\0';    
    for (i=0;i<CCRecipients.size();i++) {
        i > 0 ? strcat(cc,","):strcat(cc,"");
        strcat(cc,CCRecipients.at(i)->GetEmail());
    }

    bcc[0] = '\0';    
    for (i=0;i<BCCRecipients.size();i++) {
        i > 0 ? strcat(bcc,","):strcat(bcc,"");
        strcat(bcc,BCCRecipients.at(i)->GetEmail());
    }
// get the current date and time

    SYSTEMTIME st={0};
    ::GetSystemTime(&st);
    ::GetDateFormat(LOCALE_SYSTEM_DEFAULT,0,&st,"ddd',
                    ' dd MMM yyyy",szDate,sizeof(szDate));
    ::GetTimeFormat(LOCALE_SYSTEM_DEFAULT,TIME_FORCE24HOURFORMAT,&st,
                    "HH':'mm':'ss tt",sztTime,sizeof(sztTime));
// here it is...the main data of the message

    wsprintf(msgHeader,"DATE: %s %s\r\n", szDate, sztTime);    
    if (m_pcFromName != NULL) {
        strcat(msgHeader,"FROM: ");
        strcat(msgHeader, m_pcFromName);
        strcat(msgHeader, "\r\n");
    }
    strcat(msgHeader,"To: ");
    strcat(msgHeader, to);
    strcat(msgHeader, "\r\n");
    strcat(msgHeader,"Cc: ");
    strcat(msgHeader, cc);
    strcat(msgHeader, "\r\n");
    if (m_pcSubject != NULL) {
        strcat(msgHeader, "Subject: ");
        strcat(msgHeader, m_pcSubject);
        strcat(msgHeader, "\r\n");
    }
    if (m_pcXMailer != NULL) {
        strcat(msgHeader,"X-Mailer: ");
        strcat(msgHeader, m_pcXMailer);
        strcat(msgHeader, "\r\n");
    }
// start optional fields

    if (m_pcReplyTo != NULL) {
        strcat(msgHeader, "Reply-To: ");
        strcat(msgHeader, m_pcReplyTo);
        strcat(msgHeader, "\r\n");
    }
// start MIME versions

    strcat(msgHeader, 
           "MIME-Version: 1.0\r\nContent-type: text/plain; charset=US-ASCII\r\n");
// send header finish command

    strcat(msgHeader, "\r\n");    
// clean up

    delete to;
    delete cc;
    delete bcc;
// done    

    return msgHeader;    
}

const char* const CFastSmtp::GetLocalHostIp() 
{
    in_addr    *iaHost;
    
    if (gethostname(m_cHostName,255) != SOCKET_ERROR) {
        HOSTENT *pHe = NULL;        
        pHe = gethostbyname(m_cHostName);
        if (pHe != NULL) {
            for (int i=0;pHe->h_addr_list[i] != 0;i++) {
                iaHost = (LPIN_ADDR)pHe->h_addr_list[i];
                m_pcIPAddr = inet_ntoa(*iaHost);
            }
        }            
    } else {            
        DWORD dErr = WSAGetLastError();    
        printf("Failed to get the local ip address\r\n");
    }    

    return m_pcIPAddr;
}

const char* const CFastSmtp::GetLocalHostname() 
{    
    if (gethostname((char FAR*)m_cHostName,255) == SOCKET_ERROR)    
        printf("Failed to get the local hostname\r\n");
    return m_cHostName;
}


//**********************************************************************************

//*** Properties

//**********************************************************************************


bool CFastSmtp::GetConnectStatus()
{
    return (bCon);
}

unsigned const int CFastSmtp::GetBCCRecipientCount()
{
    return (BCCRecipients.size());
}

unsigned const int CFastSmtp::GetCCRecipientCount() 
{
    return (CCRecipients.size());
}

unsigned const int CFastSmtp::GetSocket()
{
    return (hSocket);
}

const char* const CFastSmtp::GetMessageBody() 
{
    return (m_pcMsgBody);
}

unsigned const int CFastSmtp::GetRecipientCount()
{
    return (Recipients.size());
}

const char* const CFastSmtp::GetReplyTo()  
{
    return (m_pcReplyTo);
}

const char* const CFastSmtp::GetSenderEmail() 
{
    return (m_pcFromEmail);
}

const char* const CFastSmtp::GetSenderName() 
{
    return (m_pcFromName);
}

const char* const CFastSmtp::GetSubject() 
{
    return (m_pcSubject);
}

const char* const CFastSmtp::GetXMailer() 
{
    return (m_pcXMailer);
}

void CFastSmtp::SetMessageBody(const char body[])
{
    assert(body);
    int s=strlen(body);
    if (m_pcMsgBody)
        delete [] m_pcMsgBody;
    m_pcMsgBody = new char[s+1];
    strcpy(m_pcMsgBody, body);    
}

void CFastSmtp::SetReplyTo(const char replyto[])
{
    assert(replyto);
    int s=strlen(replyto);
    if (m_pcReplyTo)
        delete [] m_pcReplyTo;
    m_pcReplyTo = new char[s+1];
    strcpy(m_pcReplyTo, replyto);
}

void CFastSmtp::SetSenderEmail(const char email[])
{
    assert(email);
    int s=strlen(email);
    if (m_pcFromEmail)
        delete [] m_pcFromEmail;
    m_pcFromEmail = new char[s+1];
    strcpy(m_pcFromEmail, email);        
}

void CFastSmtp::SetSenderName(const char name[])
{
    assert(name);
    int s=strlen(name);
    if (m_pcFromName)
        delete [] m_pcFromName;
    m_pcFromName = new char[s+1];
    strcpy(m_pcFromName, name);
}

void CFastSmtp::SetSubject(const char subject[])
{
    assert(subject);
    int s=strlen(subject);
    if (m_pcSubject)
        delete [] m_pcSubject;
    m_pcSubject = new char[s+1];
    strcpy(m_pcSubject, subject);
}

void CFastSmtp::SetXMailer(const char xmailer[])
{
    assert(xmailer);
    int s=strlen(xmailer);
    if (m_pcXMailer)
        delete [] m_pcXMailer;
    m_pcXMailer = new char[s+1];
    strcpy(m_pcXMailer, xmailer);
}

Here is the header (FastSmtp.h):
// CFastSmtp.h: interface for the Smtp class.

//

//////////////////////////////////////////////////////////////////////


#if !defined(AFX_SMTP_H__C66CDD0A_4F6F_4465_BAD6_8FA531785B5D__INCLUDED_)
#define AFX_SMTP_H__C66CDD0A_4F6F_4465_BAD6_8FA531785B5D__INCLUDED_

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


#include <winsock2.h>

#include <assert.h>

#include <vector>


const int DEFAULT_PROTOCOL = 0;
const int NO_FLAGS = 0;

class CFastSmtp  
{
public:        
    CFastSmtp();    
    virtual ~CFastSmtp();
    bool    AddRecipient(const char email[], const char name[]="");
    bool    AddBCCRecipient(const char email[], const char name[]="");
    bool    AddCCRecipient(const char email[], const char name[]="");    
    bool    ConnectServer(const char server[], const unsigned short port=NULL);
    bool    Disconnect();
    bool    GetConnectStatus();    
    const unsigned int    GetBCCRecipientCount();    
    const unsigned int    GetCCRecipientCount();
    const unsigned int    GetRecipientCount();    
    const unsigned int    GetSocket();
    const char*    const    GetLocalHostIp();
    const char*    const    GetLocalHostname();    
    const char*    const    GetMessageBody();    
    const char*    const    GetReplyTo();
    const char*    const    GetSenderEmail();
    const char*    const    GetSenderName();
    const char*    const    GetSubject();    
    const char*    const    GetXMailer();    
    bool    Send();
    void    SetMessageBody(const char body[]);    
    void    SetSubject(const char subject[]);    
    void    SetSenderName(const char name[]);    
    void    SetSenderEmail(const char email[]);    
    void    SetReplyTo(const char replyto[]);    
    void    SetXMailer(const char xmailer[]);

private:
    class CRecipient
    {
    public:
        CRecipient() 
        { 
            m_pcEmail = NULL;
        };
        CRecipient& operator=(const CRecipient& src)
        {
            if (&src != this)
            {
                if (m_pcEmail)
                    delete [] m_pcEmail;
                int s = strlen(src.m_pcEmail);
                m_pcEmail = new char[s+1];
                strcpy(m_pcEmail, src.m_pcEmail);
            }
            return (*this);
        };
        virtual ~CRecipient()
        {
            if (m_pcEmail)
                delete [] m_pcEmail;
        };
        char* GetEmail()
        {
            return m_pcEmail;
        };
        void SetEmail(const char email[])
        {
            assert(email);
            int s=strlen(email);
            if (s > 0)
            {
                m_pcEmail = new char[s+1];
                strcpy(m_pcEmail, email);
            }        
        };
    private:
        char *m_pcEmail;
    };
    bool bCon;
    char m_cHostName[MAX_PATH];
    char* m_pcFromEmail;
    char* m_pcFromName;
    char* m_pcSubject;
    char* m_pcMsgBody;
    char* m_pcXMailer;
    char* m_pcReplyTo;
    char* m_pcIPAddr;    

    WSADATA wsaData;
    SOCKET hSocket;

    std::vector<CRecipient*> Recipients;
    std::vector<CRecipient*> CCRecipients;
    std::vector<CRecipient*> BCCRecipients;    
    
    char*   _formatHeader();    
    bool    _formatMessage();
    SOCKET  _connectServerSocket(const char* server, const unsigned short port=NULL);    
};

#endif // !defined(AFX_SMTP_H__C66CDD0A_4F6F_4465_BAD6_8FA531785B5D__INCLUDED_)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here