-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
1,379 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
Simple SMTP Mailer | ||
Written by Richard Walmsley <richwalm@gmail.com> | ||
WWW: http://walmsley.gen.nz/ | ||
|
||
Description | ||
=========== | ||
A simple API used to send out e-mails. It supports attachments but lacking authentication as it wasn't required for my use. | ||
It's Windows only due to the use of its DNS lookup functions, although outside of those, it should be easy to port but as there's far more advance tools out there, it's not worth the use. | ||
No tested but should be thread-safe. | ||
|
||
Included an example. | ||
|
||
API Usage | ||
========= | ||
All functions return SMTP_ERR_SUCCESS (0) on success. | ||
|
||
The error codes are as follows; | ||
* SMTP_ERR_INVALID_STATE - Function called without a successful call to a prerequisite function. | ||
* SMTP_ERR_FAILURE - Server returned a non-success code or unable to connect to server. | ||
* SMTP_ERR_BUFFER - Out of memory or static buffer too small. The latter shouldn't happen with a valid e-mail address. | ||
* SMTP_ERR_PROTOCOL - Protocol error. Server not following the spec or there's a transfer error. | ||
* SMTP_ERR_DATA - The data passed to the function is invalid. | ||
|
||
The socket used has a receive timeout of 15 seconds. This can be adjusted by defining SMTP_BLOCKING_TIME before including ssmtp.h. The value is in milliseconds. | ||
|
||
int SMTPConnect(SMTPConn *Conn, const char *Domain, const char *HeloLine); | ||
-------------------------------------------------------------------------- | ||
Attempts to connects to the most suitable mail server. | ||
|
||
Before calling this function for the first use of a SMTPConn, ensure that SMTPConn->State is set to 0 otherwise the function may fail with SMTP_ERR_INVALID_STATE. It only needs to be set once per SMTPConn as it is then handled internally. | ||
|
||
This looks up the MX records for the domain passed and then attempts to connect to them sorted by their preference. If one fails, it'll continue to the next one. If none of them work, it'll try to connect to the server's A records as per the spec. | ||
|
||
Once connected, it'll send through the HELO line using the passed string. If the server returns an unsuccessful code, it'll disconnect and continue through the list. | ||
|
||
int SMTPAddress(SMTPConn *Conn, int Type, const char *Address); | ||
--------------------------------------------------------------- | ||
Adds a single e-mail address to the buffer. | ||
|
||
The types are as follows; | ||
* SMTP_ADDRESS_FROM | ||
* SMTP_ADDRESS_TO | ||
* SMTP_ADDRESS_CC | ||
* SMTP_ADDRESS_BCC | ||
|
||
There's no limit other then the available memory. BCC addresses aren't included into its buffer. | ||
The senders' address always needs to be sent first otherwise the function will fail with SMTP_ERR_INVALID_STATE. | ||
|
||
The address can be in either format; 'test@example.org' or '"Testing Account" <test@example.org>'. | ||
There is no checking to see if an address has been added twice. | ||
|
||
int SMTPData(SMTPConn *Conn, const char *Subject, const char *Body, SMTPAttach *Attachments); | ||
--------------------------------------------------------------------------------------------- | ||
Sends off the e-mail. | ||
|
||
Before calling this, we must have called SMTPAddress() at least twice returning successful. First with a sender and then again with a receiver. | ||
|
||
The subject line is optional. If Attachments is NULL, the e-mail will be a standard e-mail, without MIME. | ||
See the included example for further infomation on attachments. | ||
|
||
int SMTPReset(SMTPConn *Conn); | ||
------------------------------ | ||
Sends the SMTP RSET command. This clears any addresses that may have been added to the buffer. As if starting with a fresh connection. | ||
|
||
int SMTPDisconnect(SMTPConn *Conn); | ||
----------------------------------- | ||
Disconnects from the mail server. | ||
|
||
This will free any memory used by the address buffer. The SMTPConn can then be reused. | ||
|
||
License | ||
======= | ||
Distributed under the MIT License. See the included LICENSE for details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* | ||
An error-free in-memory Base64 encoder. | ||
Simple SMTP Mailer. | ||
Copyright (C) 2013 Richard Walmsley <richwalm@gmail.com> | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | ||
*/ | ||
|
||
#include <string.h> /* For memcpy() */ | ||
|
||
#include "base64.h" | ||
|
||
static const char B64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
|
||
static void EncodeBlock(unsigned char In[BASE64_IN_SIZE], unsigned char Out[BASE64_OUT_SIZE], unsigned int Length) | ||
{ | ||
unsigned int Index; | ||
|
||
for (Index = Length; Index < BASE64_IN_SIZE; Index++) | ||
In[Index] = 0; | ||
|
||
Out[0] = B64[In[0] >> 2]; | ||
Out[1] = B64[((In[0] & 0x03) << 4) | ((In[1] & 0xF0) >> 4)]; | ||
Out[2] = (unsigned char)(Length > 1 ? B64[((In[1] & 0x0F) << 2) | ((In[2] & 0xC0) >> 6)] : '='); | ||
Out[3] = (unsigned char)(Length > 2 ? B64[In[2] & 0x3F] : '='); | ||
|
||
return; | ||
} | ||
|
||
void InitEncode64(B64Stream *Stream) | ||
{ | ||
Stream->AvailIn = Stream->AvailOut = \ | ||
Stream->TotalIn = Stream->TotalOut = \ | ||
Stream->BlockSize = Stream->BlockOut = 0; | ||
|
||
return; | ||
} | ||
|
||
void Encode64(B64Stream *Stream, int Finished) | ||
{ | ||
unsigned char OutBlock[BASE64_OUT_SIZE]; | ||
|
||
/* Loop until we have no more input or unable to output. */ | ||
while (Stream->AvailIn != 0 || Stream->BlockSize != 0) { | ||
|
||
/* If anything is in our block for output, dump it. */ | ||
if (Stream->BlockOut && Stream->BlockSize != 0) { | ||
|
||
for (; Stream->BlockSize != 0; Stream->BlockSize--) { | ||
|
||
if (Stream->AvailOut == 0) | ||
return; | ||
|
||
*Stream->NextOut = Stream->Block[BASE64_OUT_SIZE - Stream->BlockSize]; | ||
Stream->NextOut++; | ||
Stream->TotalOut++; | ||
Stream->AvailOut--; | ||
} | ||
|
||
} | ||
|
||
/* Now that our buffer is empty, fill the input. */ | ||
Stream->BlockOut = 0; | ||
for (; Stream->BlockSize < BASE64_IN_SIZE; Stream->BlockSize++) { | ||
|
||
/* Out of input. This may be expected if there is no data left. */ | ||
if (Stream->AvailIn == 0) { | ||
if (!Finished || Stream->BlockSize == 0) | ||
return; | ||
break; | ||
} | ||
|
||
Stream->Block[Stream->BlockSize] = *Stream->NextIn; | ||
Stream->NextIn++; | ||
Stream->TotalIn++; | ||
Stream->AvailIn--; | ||
} | ||
|
||
/* Encode the input we have. */ | ||
EncodeBlock(Stream->Block, OutBlock, Stream->BlockSize); | ||
|
||
Stream->BlockSize = BASE64_OUT_SIZE; | ||
memcpy(Stream->Block, OutBlock, Stream->BlockSize); | ||
|
||
Stream->BlockOut = 1; | ||
} | ||
|
||
return; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#ifndef BASE64_H | ||
#define BASE64_H | ||
|
||
#define BASE64_OUT_SIZE 4 | ||
#define BASE64_IN_SIZE 3 | ||
|
||
typedef struct B64Stream { | ||
unsigned int AvailIn; | ||
unsigned int TotalIn; | ||
unsigned char *NextIn; | ||
|
||
unsigned int AvailOut; | ||
unsigned int TotalOut; | ||
char *NextOut; | ||
|
||
/* Internal cache. */ | ||
unsigned int BlockSize; | ||
int BlockOut; /* Direction of block. (Input or Output) */ | ||
unsigned char Block[BASE64_OUT_SIZE]; | ||
} B64Stream; | ||
|
||
void InitEncode64(B64Stream *Stream); | ||
void Encode64(B64Stream *Stream, int Finished); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/* | ||
Simple set of functions used to prevent sending small amounts of data. | ||
Simple SMTP Mailer. | ||
Copyright (C) 2013 Richard Walmsley <richwalm@gmail.com> | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | ||
*/ | ||
|
||
#include <string.h> | ||
#include <stdarg.h> | ||
|
||
#include "cbuffer.h" | ||
|
||
int CFlush(CSendBuffer *Buffer) | ||
{ | ||
int Return; | ||
|
||
if (Buffer->Cursor > 0) { | ||
|
||
Return = Buffer->Callback(Buffer->CallbackData, Buffer->Data, Buffer->Cursor); | ||
if (Return != 0) | ||
return Return; | ||
Buffer->Cursor = 0; | ||
|
||
} | ||
|
||
return 0; | ||
} | ||
|
||
int CSend(CSendBuffer *Buffer, const char *Data, unsigned int Size) | ||
{ | ||
unsigned int BufferAvailable; | ||
int Return; | ||
|
||
while (Size > 0) { | ||
|
||
BufferAvailable = Buffer->Size - Buffer->Cursor; | ||
if (BufferAvailable > Size) | ||
BufferAvailable = Size; | ||
|
||
memcpy(&Buffer->Data[Buffer->Cursor], Data, BufferAvailable); | ||
|
||
Size -= BufferAvailable; | ||
Data += BufferAvailable; | ||
|
||
Buffer->Cursor += BufferAvailable; | ||
if (Buffer->Cursor >= Buffer->Size) { | ||
|
||
Return = Buffer->Callback(Buffer->CallbackData, Buffer->Data, Buffer->Cursor); | ||
if (Return != 0) | ||
return Return; | ||
Buffer->Cursor = 0; | ||
} | ||
|
||
} | ||
|
||
return 0; | ||
} | ||
|
||
int CSendStrings(CSendBuffer *Buffer, ...) | ||
{ | ||
va_list Args; | ||
char *Arg; | ||
size_t Length; | ||
int Return; | ||
|
||
va_start(Args, Buffer); | ||
|
||
Arg = va_arg(Args, char*); | ||
while (Arg) { | ||
|
||
Length = strlen(Arg); | ||
Return = CSend(Buffer, Arg, Length); | ||
if (Return != 0) { | ||
va_end(Args); | ||
return Return; | ||
} | ||
Arg = va_arg(Args, char*); | ||
|
||
} | ||
|
||
va_end(Args); | ||
return 0; | ||
} | ||
|
||
void CInit(CSendBuffer *Buffer, char *Data, unsigned int Size, int (*Callback)(void *, char *, unsigned int), void *CallbackData) | ||
{ | ||
Buffer->Data = Data; | ||
Buffer->Size = Size; | ||
Buffer->Cursor = 0; | ||
|
||
Buffer->Callback = Callback; | ||
Buffer->CallbackData = CallbackData; | ||
|
||
return; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#ifndef CBUFFER_H | ||
#define CBUFFER_H | ||
|
||
typedef struct CSendBuffer { | ||
char *Data; | ||
unsigned int Size, Cursor; | ||
void *CallbackData; | ||
int (*Callback)(void *, char *, unsigned int); | ||
} CSendBuffer; | ||
|
||
int CFlush(CSendBuffer *Buffer); | ||
int CSend(CSendBuffer *Buffer, const char *Data, unsigned int Size); | ||
int CSendStrings(CSendBuffer *Buffer, ...); | ||
void CInit(CSendBuffer *Buffer, char *Data, unsigned int Size, int (*Callback)(void *, char *, unsigned int), void *CallbackData); | ||
|
||
#endif |
Oops, something went wrong.