Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background::[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which use a logographic writing system and need larger font sizes.
***/

/*{{{*/
body {font-size:0.8em;}

#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}

.subtitle {font-size:0.8em;}

.viewer table.listView {font-size:0.95em;}

.htmlarea .toolbarHA table {border:1px solid ButtonFace; margin:0em 0em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see AdvancedOptions
Our API provides access to various useful back-end functions in Smartmessages, in particular getting a list of mailing lists, subscribing and unsubscribing, and getting info on recipients (including mailing history).
Our API may be overkill for some tasks, particularly for simple synchronisation purposes - our [[Callback|Callbacks]] system may be all you need.
!!What's an API?
An API is an [[Application Programming Interface|http://en.wikipedia.org/wiki/Api]], and presents an access point through which you can write code to talk to Smartmessages behind-the-scenes functions without all that visual HTML stuff to get in the way. This might help you to:
* Build your own subscribe/unsubscribe pages
* Integrate with your CRM system
* Anything else you might want to do!
!!Implementation
The API is an [[RPC|http://en.wikipedia.org/wiki/Remote_Procedure_Call]]-style interface, providing responses suitable for direct consumption by ~JavaScript ([[JSON|http://en.wikipedia.org/wiki/Json]]) and PHP (serialised arrays), XML (everything else), plus simple HTML output to help you debug your code.
The initial focus of our API has been to make basic information available, and provide you with sufficient resources for you to build your own subscribe and unsubscribe pages. If you don't want to go that far, you can [[automate our subscribe and unsubscribe pages|Subscribing]] anyway. There are plenty more functions yet to come!
''Note that all string data, parameters and responses must use the ~ISO-8859-1 character set''.
We reserve the right to withdraw API access, or to place restrictions on the quantity and/or rate of connections and requests.
!!How To Use The API
Firstly you'll need to get API access enabled for your login ID, or we can create a new login for you that has appropriate permissions. Next, go to your account tab inside smartmessages and copy the API key shown below your account name. If you have access to multiple accounts, they will have different API keys. Then you need to start writing your scripts (using PHP, Java, ASP, Ruby, etc) that call the functions we provide.
The quickest way to get started is with PHP using our [[API wrapper class|APIExamples]], which implements all features and is ready to go. If you're using another language, you might like to use that code as a basis.
The initial access point is https&#58;&#47;/www.smartmessages.net/api/, but when you log in, you will be provided with an endpoint URL that you should direct subsequent calls to. This allows us future flexibility in how we support the API.
Though we provide JSON output, it's not a good idea to implement access to this API using client-side ~JavaScript, because it's not possible to do so without exposing your login credentials and API key, which would compromise the security of your data.
!!Errors and Feedback
Any function that fails for some reason will return a status value of false, usually accompanied by an error code, and a plain text error message. Some responses contain an additional message field for additional information about the function you just called.
!!!Defined error codes
* ~ERR_INCORRECT_ID_PASS: 1
* ~ERR_UNKNOWN_MISSING_METHOD: 2
* ~ERR_INCORRECT_METHOD_PARAMS: 3
* ~ERR_NO_PERMISSION: 4
* ~ERR_INVALID_EMAIL: 5
* ~ERR_USER_NOT_FOUND: 6
* ~ERR_ALREADY_SUBSCRIBED: 7
* ~ERR_SESSION_EXPIRED: 8
* ~ERR_MISSING_API_KEY: 9
* ~ERR_LOGIN_FAILED_SUSPENDED: 10
* ~ERR_LOGIN_STILL_SUSPENDED: 11
* ~ERR_INVALID_LIST_ID: 12
* ~ERR_SUBSCRIPTION_NOT_FOUND: 13
* ~ERR_INVALID_CUSTOMER_ID: 14
* ~ERR_LIST_UPLOAD_FAILED: 15
* ~ERR_LIST_NOT_YOURS: 16
* ~ERR_UNKNOWN_LIST: 17
* ~ERR_ACCOUNT_NOT_FOUND: 18
* ~ERR_NOT_YET_IMPLEMENTED: 19
* ~ERR_INVALID_URL: 20
* ~ERR_UNKNOWN_UPLOAD: 21
* ~ERR_INVALID_NAME: 22
* ~ERR_INVALID_CAMPAIGN_ID: 23
* ~ERR_CAMPAIGN_NOT_YOURS: 24
* ~ERR_TEMPLATE_NOT_FOUND: 25
* ~ERR_INCORRECT_API_KEY: 26
* ~ERR_TEMPLATE_NOT_YOURS: 27
* ~ERR_BAD_URL: 28
* ~ERR_DELETED: 29
* ~ERR_INVALID_MAILSHOT_ID: 30
* ~ERR_INTERNAL: 99
Generally you should never receive an error 99 - please report it to us if you do.
!!Output formats
People like to work in different ways, so we provide output in multiple formats which you can choose as best fits your application by specifying which one you want when you log in:
*''php'': This is the result of serialising PHP arrays. If you're working in PHP (as we are), this is by far the easiest format to deal with as all you need to do is [[unserialize($response)|http://www.php.net/manual/en/function.unserialize.php]] to have all the response data in a ready-to use format. This is the default format, and is also what our PHP client class uses.
*''json'': [[JavaScript Object Notation|http://en.wikipedia.org/wiki/Json]] is an increasingly popular markup for web applications due to its compact syntax, ease of parsing and cross-language support.
*''xml'': XML is very popular and flexible, so we provide simple XML output too, though it's a bit more verbose and slower than json or php, so use them if you can.
*''html'': This outputs a simple full HTML page with a debug dump of the response on. This is only of use for debugging.
*''htmlfragment'': Outputs the same data as html format, but without html, head and body tags, useful for debugging if you're making several API calls.
!!Functions
Exact parameter names and response labels are given in italic text. Mandatory parameters are bold. All functions except login require an //''accesskey''// parameter which you will receive in the response to a successful login call, and this parameter is not shown on parameter lists.

!!Connection functions
!!!login
!!!!Parameters:
*//''username''//: the email address that you use to log into smartmessages
*//''password''//: your password
*//''apikey''//: the key you copied from your account tab.
*//outputformat//: an optional parameter to set the format to one of xml, json, php (the default), html or htmlfragment
!!!!Response
*//accesskey// => string 'abc123'
*//endpoint// => string 'https&#58;&#47;/www.smartmessages.net/api/'
*//status// => boolean true
*//accountname// => string 'Your account name'
*//username// => string 'Your login email address'
*//expires// => integer timestamp
This is the first function you need to call. You should check for the presence of the 'status' value and check that it is not false. You will also be provided with an access key which you will need for all subsequent function calls, and you should use the endpoint value to form the basis of your access ~URLs. The timestamp indicates when your session will expire, though it is extended every time you make a function call.
You need to provide your id and password as well as the API key because the API key is common to all users in an account, but permissions are defined per user.
So that you don't need to expose your own login credentials in source code you may provide to your own customers, we can create additional accounts that have ~API-only access that are unique for your application. Feel free to use your own ID while developing, and request a new separate ID from us when you're ready to deploy.
!!!ping
!!!!Parameters:
*None
!!!!Response:
*//status// => boolean
Does nothing except refresh your access key. Use this if you want to keep your access key valid for an extended period without actually doing anything.
!!!logout
!!!!Parameters:
*None
!!!!Response:
*//status// => boolean
Call this when you've finished using the API. After this call, your access key will no longer work, and you'll have to request a new one using login. If you don't call logout, your key will eventually expire anyway, but it helps us free up resources and thus keep smartmessages performance high for everyone.
!!Template functions
Note that all imported templates are subject to content filtering for security purposes. Generally this won't make any visible difference, but tags such as scripts and iframes will be removed, along with script-related attributes.
!!!gettemplates
!!!!Parameters:
*//includeglobal//: Boolean; whether to include the standard smartmessages-supplied templates. Defaults to false.
*//includeinherited//: Boolean; whether to include templates inherited from parent accounts. Defauts to true.
!!!!Response
*//status// => boolean
*//templates// => array
Returns an array of all templates that you have access to.
!!!addtemplate
!!!!Parameters
*//''name''//: The name of the new template, max 100 characters.
*//''html''//: The HTML part of the template.
*//''plain''//: The plain-text half of the template.
*//''subject''//: The default subject line, max 100 characters.
*//description//: A description of the new template, max 255 characters.
*//generateplain// Boolean; whether to create a plain text version from the html version. Defauts to false. The ''plain'' parameter is ignored if this is set.
*//language// The ~ISO-639-1 language that this template is in, defaults to 'en' for English.
!!!!Response
*//status// => boolean
*//templateid// => integer
Creates a new template. This should use an HTTP POST method in order to handle the large data size of templates.
!!!addtemplatefromurl
!!!!Parameters
*//''name''//: The name of the new template, max 100 characters.
*//''url''//: A URL of the web page you want to import.
*//''subject''//: The default subject line, max 100 characters.
*//description//: A description of the new template, max 255 characters.
!!!!Response
*//status// => boolean
*//templateid// => integer
Creates a new template from a URL. This is useful if you develop or generate your templates on an external system. A plain-text version is created automatically.
!!!updatetemplate
!!!!Parameters
*//''templateid''// integer
*//''name''//: The new name of the template, max 100 characters.
*//''html''//: The HTML part of the template.
*//''plain''//: The plain-text half of the template.
*//''subject''//: The default subject line, max 100 characters.
*//description//: A description of the new template, max 255 characters.
*//generateplain// Boolean; whether to create a plain text version from the html version. Defauts to false. The ''plain'' parameter is ignored if this is set.
*//language// The ~ISO-639-1 language that this template is in, defaults to 'en' for English.
!!!!Response
*//status// => boolean
*//templateid// => integer
Creates a new template. Note you can only update templates that are in your account - not global or inherited ones. This should use an HTTP POST method in order to handle the large data size of templates.
!!!deletetemplate
!!!!Parameters
*//''templateid''// integer
!!!!Response
*//status// => boolean
Deletes a template. Note you can only delete templates that are in your account - not global or inherited ones.
''Warning: also deletes any mailshots that used this template''.
!!Campaign functions
Campaigns are groups of mailshots organised into folders - don't get them confused with mailshots.
!!!getcampaigns
!!!!Parameters:
*None
!!!!Response
*//status// => boolean
*//campaigns// => array
Returns a list of all campaign ids and names in your account.
!!!addcampaign
!!!!Parameters
*//''name''//: The name of the new campaign, max 100 characters.
!!!!Response
*//status// => boolean
*//campaignid// => integer
Creates a new campaign folder into which you can put new mailshots, or move existing mailshots.
!!!updatecampaign
!!!!Parameters
*//''campaignid''// => integer
*//''name''//: The new name for the campaign, max 100 characters.
!!!!Response
*//status// => boolean
Changes the name of an existing campaign. Note that campaign names don't have to be unique, though it's in your own interests to make them so!
!!!deletecampaign
!!!!Parameters
*//''campaignid''// => integer
!!!!Response
*//status// => boolean
Deletes a campaign.
''Warning: also deletes any mailshots contained in the campaign''.
!!!getcampaignmailshots
!!!!Parameters
*//''campaignid''// => integer
!!!!Response
*//status// => boolean
*//mailshots// => array
Returns an array of useful information about all the mailshots contained by a campaign.
!!Mailshot functions
See also getcampaignmailshots
!!!getmailshot
!!!!Parameters:
*//''mailshotid''//: The integer id of the mailshot you want
!!!!Response:
*//status// => boolean
*//mailshot// => array
**//name// => string
**//subject// => string
**//mailinglistid// => integer The id of the mailing list this mailshot is to
**//templateid// => integer The id of the template being sent
**//campaignid// => integer The id of the campaign this mailshot is stored in
**//status// => string 'unsent', 'complete', 'sending', 'error' etc
**//date_sent// => an ~ISO-8601 date in '~YYYY-MM-DD HH:MM:SS', or a zero date if it's unsent, of the time the mailshot was sent
**//from_address// => string The email address the message is sent from
**//from_name// => string The name the message is sent from
**//replyto// => string The email address replies go to, if different from the from address
**//date_completed// => an ~ISO-8601 date in '~YYYY-MM-DD HH:MM:SS', or a zero date if it's unsent or incomplete, of the time the mailshot completed
**//thumbnail_url// => string A URL of an image of the mailshot as sent (scaled to fit in a 320x320 pixel box)
**//preview_url// => string A URL of a web version of the mailshot as sent
**//recordcount// => integer number of subscribers in the uploaded list (not populated until upload complete)
**//messagecount// => integer Number of messages in this mailshot
**//opencount// => integer number of openings recorded
**//clickcount// => integer number of clicks recorded
Gets information about an existing mailshot.
!!!sendmailshot
!!!!Parameters
*//''templateid''//: The id of the template to send.
*//''listid''//: The id of the mailing list to send to.
*//title//: The title of the new mailshot, max 100 characters. If omitted, will generate a name based on the date.
*//''campaignid''//: The id of the campaign to put the mailshot in.
*//subject//: The subject template to use (allowed syntax is the same as for templates). Will use the template's default subject if omitted.
*//''fromaddr''//: The email address to use as the from address (should be in a domain you have set up DKIM and SPF for).
*//fromname//: The name to use as the sender.
*//replyto//: An address that replies should go to, if different to the from address.
*//when//: When to send the mailshot. Either the word 'now' (the default), or an ~ISO-8601 date in '~YYYY-MM-DD HH:MM:SS' format.
*//elements//: For future expansion, ignore for now.
!!!!Response
*//status// => boolean
*//mailshotid// => integer
Creates a new mailshot and schedules it for sending.
!!!getmailshotclicks
!!!!Parameters:
*//''mailshotid''//: The integer id of the mailshot you want
*//ascsv//: Boolean. Whether to return the result in CSV format
!!!!Response:
*//status// => boolean
*//clicks// => array
**//url// => string The link they clicked on
**//email// => string The address of the recipient that clicked
**//timestamp// => an ~ISO-8601 UTC date in '~YYYY-MM-DD HH:MM:SS'
Gets a list of clicks relating to a particular mailshot. If the 'ascsv' parameter is supplied and true, results will be provided in CSV format, which is smaller, faster and easier to handle (just save it directly to a file) than other formats.
!!!getmailshotopens
!!!!Parameters:
*//''mailshotid''//: The integer id of the mailshot you want
*//ascsv//: Boolean. Whether to return the result in CSV format
!!!!Response:
*//status// => boolean
*//opens// => array
**//email// => string The address of the recipient that clicked
**//timestamp// => an ~ISO-8601 UTC date in '~YYYY-MM-DD HH:MM:SS'
Gets a list of opens relating to a particular mailshot. If the 'ascsv' parameter is supplied and true, results will be provided in CSV format, which is smaller, faster and easier to handle (just save it directly to a file) than other formats.
//Note that we record a single extra open event for recipients that click if they do not have an open logged already. This allows us to avoid the nonsensical situation where someone has clicked by not opened, which could lead to unique clicks being larger than unique opens.//
!!!getmailshotunsubs
!!!!Parameters:
*//''mailshotid''//: The integer id of the mailshot you want
*//ascsv//: Boolean. Whether to return the result in CSV format
!!!!Response:
*//status// => boolean
*//unsubs// => array
**//email// => string The address of the recipient that clicked
Gets a list of unsubscribes relating to a particular mailshot. If the 'ascsv' parameter is supplied and true, results will be provided in CSV format, which is smaller, faster and easier to handle (just save it directly to a file) than other formats.
!!!getmailshotbounces
!!!!Parameters:
*//''mailshotid''//: The integer id of the mailshot you want
*//''ascsv''//: Boolean. Whether to return the result in CSV format
!!!!Response:
*//status// => boolean
*//bounces// => array
**//email// => string The address of the recipient that clicked
**//code// => integer The bounce reason code
**//type// => string Hard, soft or other
**//reason// => string Text description of the bounce, for example 'Soft bounce - Mailbox full'
**//timestamp// => an ~ISO-8601 UTC date in '~YYYY-MM-DD HH:MM:SS'
Gets a list of bounces relating to a particular mailshot. This is the same information as is downloadable from the contacts page, except that this is for a single mailshot, not a whole list (which might cover multiple mailshots). If the 'ascsv' parameter is supplied and true, results will be provided in CSV format, which is smaller, faster and easier to handle (just save it directly to a file) than other formats.
!!List functions
!!!addlist
!!!!Parameters
*//''name''//: The name of the new list, max 100 characters.
*//description//: A description of the new list, max 255 characters.
*//visible//: Boolean. Whether the new list should be publicly visible, defaults to true.
!!!!Response
*//status// => boolean
*//listidid// => integer
Creates a new mailing list, ready for you to upload subscribers into. List names do not have to be unique.
!!!updatelist
!!!!Parameters
*//''listid''// => integer
*//''name''//: The new name for the list, max 100 characters.
*//''description''//: The new description for the list, max 255 characters.
*//''visible''//: Boolean. Whether the list should be publicly visible
!!!!Response
*//status// => boolean
Changes the properties of an existing list. Note that all parameters are mandatory.
!!!deletelist
!!!!Parameters
*//''listidid''// => integer
!!!!Response
*//status// => boolean
Deletes a list.
''Warning: also deletes any mailshots that have used this list''.
!!!getlists
!!!!Parameters:
*//showall//: (optional) Whether to include all mailing lists, or just those set to 'visible' (the default). 1 for true, 0 for false.
!!!!Response (example data):
*//status// => boolean
*//mailinglists// => array
**341897 => array
***//id// => int 341897
***//name// => string 'Announcements'
***//description// => string 'Occasional information releases'
***//visible// => boolean true
**341886 = array
***//id// => int 341886
***//name// => string 'Newsletter'
***//description// => string 'Regular monthly news, hints & tips'
***//visible// => boolean true
This function returns a list of all the mailing lists that are available in your account that are set to be visible (editable on each mailing list page). The response contains the list ID, its name, and a description of each list, and the array of lists is also indexed by the list ID. Normally the list returned only includes lists that are set to visible, i.e. those that appear on the default landing page; If you add the 'showall' boolean parameter ad set it to 1, the response will include all lists, not just those that are marked as visible. The response includes a 'visible' property for each list which you can use to decide whether to display the list in your own pages.
!!!getlist
!!!!Parameters:
*//''listid''//: The integer id of the list you want
*//ascsv//: Boolean. Whether to return the result in CSV format
!!!!Response:
*//status// => boolean
*//list// => array
** Each entry is a large structure similar to what is returned by //''getuserinfo''//.
Gets a complete list of recipients on a mailing list. If the 'ascsv' parameter is supplied and true, results will be provided in CSV format, which is smaller, faster and easier to handle (just save it directly to a file) than other formats.
''We //strongly// recommend that you use the ascsv option with this function as the response can be extremely large in PHP, JSON or XML formats, extending to hundreds of megabytes for large lists, taking a correspondingly long time to download, and possibly causing memory problems in client code. For this reason, this function defaults to CSV format.''
!!!getlistunsubs
!!!!Parameters
*//''listid''//: The id of the list you want to get unsubscibes from (obtained using the getlists function)
!!!!Response (example data):
*//status// => boolean
*//unsubscribes// => array
**string 'user1@example.com'
**string 'user2@example.com'
**string 'user3@example.com'
Provides a list of all addresses that have unsubscribed from the given list. Note that unsubscribes are retained even if the list is empty, and used to suppress unsubscribed addresses from subsequent uploads. We suggest you occasionally download unsubscribes in order to update your own copies of mailing lists (or make use of our callbacks in order to retain real-time sync).
!!List upload functions
!!!uploadlist
!!!!Parameters:
*//''listid''//: The integer id of the list you want to upload into (obtained using the getlists function)
*//''source''//: A short string describing where this list came from, for example if it's a bought list, the supplier name and order reference. This is used to retain audit trails of your subscribers.
*//definitive//: A boolean value indicating whether this upload is to be considered definitive data that should overwrite any existing data you have for each recipient for the included fields. See MailingLists for more info on the behaviour behind this. Defaults to false.
*//replace//: A boolean value indicating whether anyone already on this list that is not in this new upload should be removed. The default behaviour is to add to the list (i.e. false).
*//firstlinefields//: A boolean value indicating whether the first line of the file contains field names (note that these must match allowed field names). Defaults to false.
*//''file''//: The list file
!!!!Response:
*//status// => boolean
*//uploadid// => integer
This is a complex function used for uploading entire mailing lists in one go. It differs from the rest of our ~APIs in that it requires that you use an HTTP POST containing a multipart/form-data MIME body. Our reference PHP implementation does this for you and may provide a good basis for you to write code in other languages.
Currently the list file must be in standard [[RFC4180|http://www.rfc-editor.org/rfc/rfc4180.txt]] CSV format - comma delimited, optional double-quote delimiter escaping, double quotes escaped by themselves. This format can be exported from programs like Excel, Filemaker, Access, ~QuickBooks and numerous CRM packages.
The uploading process is asynchronous - this function will return when the physical file transfer is complete, but the actual import of the data takes longer, so you need to monitor its progress and do not send mailshots to the new list until it is complete. This function returns an integer identifier that can be used to query the status of an upload using the getuploadinfo call. You may only submit a single list file per request, and it can be compressed as a zip archive (in which case only the first file inside the archive will be used). There is a limit of 50Mb (uncompressed size).
In the absence of field names in the upload, the importer will fall back to whatever the field list is set to for the account, and if that is not set, to our default field order. The account field order can be set on the settings page, or though the API call 'setimportfields'.
!!!getuploads
!!!!Parameters:
*//''listid''//: The integer id of the list you want upload info for (obtained using the getlists function)
!!!!Response:
*//status// => boolean
*//uploads// => array
**0 => array
***//id// => integer the upload ID
***//status// => string 'pending', 'in progress', 'cancelled', 'complete', 'error' etc
***//progress// => integer (percentage)
***//cancelled// => boolean false (whether the upload has been cancelled)
***//filename// => string 'mylist.csv'
***//recordcount// => integer number of subscribers in the uploaded list (not populated until upload complete)
***//badcount// => integer number of invalid addresses in the uploaded list (not populated until upload complete)
***//groupcount// => integer number of addresses that look like group addresses in the uploaded list (not populated until upload complete)
***//uploaddate// => date and time (~ISO-8601 format) the upload completed (not populated until upload complete)
This function gets a history of all uploads, including recent ones. Typically you should call this function when monitoring an upload's progress in preference to the getuploadinfo function as it's faster and returns less information that's not relevant to the upload progress (even though it returns info on more than one upload).
!!!getuploadinfo
!!!!Parameters:
*//''listid''//: The integer id of the list you want upload info for (obtained using the getlists function)
*//''uploadid''//: The integer id of the particular upload you want info for (obtained using the getuploads or uploadlist functions)
!!!!Response:
*//status// => boolean
*//upload// => array
**//id// => integer The upload ID
**//status// => string 'pending', 'in progress', 'cancelled', 'complete', 'error' etc
**//progress// => integer (percentage)
**//cancelled// => boolean false (whether the upload has been cancelled)
**//filename// => string 'mylist.txt'
**//recordcount// => integer number of subscribers in the uploaded list (not populated until upload complete)
**//badcount// => integer number of invalid addresses in the uploaded list (not populated until upload complete)
**//groupcount// => integer number of addresses that look like group addresses in the uploaded list (not populated until upload complete)
**//uploaddate// => date and time (~ISO-8601 format) the upload completed (not populated until upload complete)
**//badaddresses// => array The array of invalid email addresses, if any. 
*** 0 => 'invalid@example.'
**//groupaddresses// => array The array of group email addresses, if any. 
*** 0 => 'sales@example.com'
*** 1 => 'customerservices@example.com'
**//definitive// => boolean true (whether the upload was uploaded in definitive mode - see the uploadlist function)
**//replace// => boolean true (whether the upload was uploaded in replace mode - see the uploadlist function)
**//firstlinefields// => boolean true (whether the upload had field names in its first line - see the uploadlist function)
**//contactcount// => integer number of entirely new contacts in this list (not populated until upload complete)
**//subcount// => integer number of new subscriptions in this list (not populated until upload complete)
**//suppressunsubcount// => integer number of unsubscribes suppressed from this upload (not populated until upload complete)
**//suppressspamcount// => integer number of spam reporters suppressed from this upload (not populated until upload complete)
**//suppressbouncecount// => integer number of known bouncing addresses suppressed from this upload (not populated until upload complete)
**//uploadbyid//: integer The ID of the user that did the upload - can be fed into the getuserinfo function
**//source//: A short string describing where this list came from, see uploadlist for details
!!!cancelupload
!!!!Parameters:
*//''listid''//: The integer id of the list the upload is in (obtained using the getlists function)
*//''uploadid''//: The integer id of the particular upload you want to cancel (obtained using the getuploads or uploadlist functions)
!!!!Response:
*//status// => boolean
If an upload has 'pending' or 'in progress' status, it can be cancelled, and none of the addresses on it will appear on the list and none of the field data changed by it will be applied.
!!Subscriber functions
!!!subscribe
!!!!Parameters
*//''address''//: The email address you want to subscribe
*//''listid''//: The id of the list you want to subscribe to (obtained using the getlists function)
*//name//: Optionally, the name you want to give to this subscriber. Goes into the 'Dear' field within smartmessages, usually used when addressing the recipient, e.g. 'John', 'Dr Who', 'Mr President', 'Gnasher' etc.
*//title//: Optionally, the title name you want to give to this subscriber.
*//firstname//: Optionally, the subscriber's first name.
*//lastname//: Optionally, the subscriber's last name (surname).
*//companyname//: Optionally, the subscriber's company name.
!!!!Response:
*//status// => boolean
*//msg// => string optional message
Doesn't need much explanation! If your subscription policy is confirmed or double opt-in (which it is by default), your recipients will receive a confirmation message which they may need to respond to before they receive messages from this list. If you subscribe someone who is already on the list, you will not get an error, but you will receive an additional //msg// property in the response saying so. The optional naming fields provide an easy way to add someone to a list and record their name in one go without having to call setuserinfo later, so it's ideal as something to work behind a signup form on your web site.
!!!unsubscribe
!!!!Parameters
*//''address''//: The email address you want to unsubscribe
*//''listid''//: The id of the list you want to unsubscribe from (obtained using the getlists or getuserinfo functions)
!!!!Response
*//status// => boolean
If you try to unsubscribe someone from a list that is not on it, you will receive an error response. Unsubscribes take effect immediately.
!!!getuserinfo
!!!!Parameters
*//''address''//: The email address you want to get info on.
!!!!Response (example data):
*//status// => boolean true
*//userinfo// => array
**//email// => string 'user@example.com'
**//ownerdata// => string 'abc123'
**//title// => string 'Mr'
**//initials// => string 'FJ'
**//jobtitle// => string 'Marketing Director'
**//firstname// => string 'Finbar'
**//lastname// => string 'Jones'
**//dear// => string 'Mr Jones'
**//companyname// => string 'Example Marketing'
**//address1// => string 'Example House'
**//address2// => string 'Noodle Road'
**//address3// => string
**//county// => string
**//posttown// => string 'London'
**//postcode// => string '~SE1 5OK'
**//country// => string 'GB'
**//phone// => string '020 8123456'
**//fax// => string 
**//mobile// => string 
**//dob// => string '1971-05-27'
**//sex// => string 'm'
**//url// => string 'http&#58;&#47;/www.example.com/'
**//timezone// => string 'Europe/London'
**//custom1// => string 'custom value 1'
**//custom2// => string 'custom value 2'
**...
**//custom31// => string 'custom value 31'
**//custom32// => string 'custom value 32'
**//subscriptions// => array
***0 => array
****//listid// => int 341897
****//name// => string 'Announcements'
****//description// => string 'Occasional information releases'
****//visible// => boolean true
***1 => array
****//listid// => int 341886
****//name// => string 'Newsletter'
****//description// => string 'Regular monthly news, hints & tips'
****//visible// => boolean true
***2 => array
****//listid// => int 341889
****//name// => string 'Test list'
****//description// => string
****//visible// => boolean false
**//mailshots// => array
***0 => array
****//mailshotid// => int 33988
****//name// => string 'First test'
****//date_sent// => string '2007-07-06 14:20:00'
****//listid// => int 341889
****//previewurl// => string 'http&#58;&#47;/www.smartmessages.net/web/3939_33988_'
***1 => array
****//mailshotid// => int 33989
****//name// => string 'Example July Newsletter'
****//date_sent// => string '2007-07-06 15:20:24'
****//listid// => int 341886
****//previewurl// => string 'http&#58;&#47;/www.smartmessages.net/web/3939_33989_'
This returns lots of useful information about the recipient. You can see all their personal data, their current subscriptions (including those to invisible lists), and a list of all the messages they have been sent (along with preview ~URLs so you can see a message like the one they were sent). The list of personal data fields is subject to change, but we'll try to only add fields rather than take them away.
!!!setuserinfo
!!!!Parameters
*//''address''//: The email address you want to get info on.
*//''userinfo''//: An array of properties to set
!!!!Response:
*//status// => boolean
Provides a counterpart to the getuserinfo function for setting personal data, perhaps to sync with your CRM system, or provide storage back-end for a custom form. A user's properties have the same names as those returned from getuserinfo, but you need to wrap them in an HTML array style query string - there is a function in the [[example code|APIExamples]] to do that for you. Note that you CANNOT change a user's email address. If you need to change an email address, unsubscribe the current address and re-subscribe under the new address.

Some fields have input constraints:
*Currently only ~ISO-8859-1 encoding is supported //(likely to change in future)//
*Most address fields are limited to 100 characters
*Phone numbers are limited to 20 characters
*Dates must be in ~ISO-8601 ~YYYY-MM-DD format
*Country requires a 2-character ~ISO-3166 code (Notably the UK is 'GB' in this scheme)
*Language requires a 2-character ~ISO-639-1 code
*Sex may be 'm', 'f', or 'unknown' (the default)
*Only custom fields are allowed to contain line breaks
*Custom fields are limited to 255 characters

Fields that are not set are not changed, fields that are set but empty will be cleared.

The meaning of custom fields is entirely up to you, and you are limited to 32 custom fields.
!!Account-level functions
!!!getspamreporters
!!!!Parameters
*None
!!!!Response (example data):
*//status// => boolean
*//spamreporters// => array
**string 'user1@example.com'
**string 'user2@example.com'
**string 'user3@example.com'
Provides a list of addresses that have reported emails from you as spam, at ~ISPs that we receive such reports from. Note that these are treated account-wide - users are unsubscribed from all your lists and prevented form being added to any list in future - it's just not worth trying to retain such recipients.
!!!getcallbackurl
!!!!Parameters:
*None
!!!!Response:
*//status// => boolean
*//url// => text
Retrieve the callback URL for your account.
!!!setcallbackurl
!!!!Parameters:
*//''url''//: text ~'http://www.example.com/callback.php' (put your callback URL here)
!!!!Response:
*//status// => boolean
Set the callback URL for your account. This must be a complete, valid URL using either HTTP or HTTPS protocol. Note that if your callback URL ever fails to respond to requests in the time allowed, or returns error codes, it will be cleared.
!!!getfieldorder
!!!!Parameters:
*None
!!!!Response (default fields shown)
*//status// => boolean
*//fields// => array
**0 => emailaddress
**1 => ownerdata
**2 => title
**3 => initials
**4 => jobtitle
**5 => firstname
**6 => lastname
**7 => dear
**8 => companyname
**9 => address1
**10 => address2
**11 => address3
**12 => posttown
**13 => county
**14 => postcode
**15 => country
**16 => phone
**17 => fax
**18 => mobile
**19 => dob
**20 => sex
**21 => custom1
**...
**32 => custom32
**33 => preferred_format
**34 => preferred_format_sms
**35 => preferred_language
**36 => url
**37 => crm_id
This function retrieves the current default import field order for your account. If you have not set a field import order, then you will get back the default order (as shown). The same functionality is available on the account settings page.
!!!setfieldorder
!!!!Parameters:
*//fields// => array (example shown)
**0 => emailaddress
**1 => firstname
**2 => lastname
!!!!Response
*//status// => boolean
Using this function you can set the default import order for subsequent uploads. This is particularly useful if you frequently upload lists with new subscriber data as you can set up smartmessages to match the export format of whatever database or spreadsheet you're using. You simply provide an array of the fields you want in the order you want. The fields you specify must be a subset of our default set (see the getfieldorder function for what they are); Fields cannot appear more than once; If the list you provide contains field names we don't know, the whole request will be ignored and will be rejected with a false status value. The field list ''must'' contain 'emailaddress' - a list is not any use without it! The same functionality is available on the account settings page.
!!Utility functions
!!!validateaddress
!!!!Parameters:
*//''address''//: string email address
!!!!Response:
*//status// => boolean
*//valid// => boolean
A utility function to assess whether an email address is valid. This is the same check as we use internally to spot bad addresses during uploads. Just submit an address and check the value of the 'valid' response property.
We provide a client wrapper class for our [[API]] in PHP which you can see [[here|http://www.smartmessages.net/SmartmessagesAPI.class.phps]]. Example code demonstrating all available functions is [[here|http://www.smartmessages.net/SmartmessagesAPIexamples.phps]]. Note that the example script will not work as is - you will need to substitute your own login ID, password and API key.

We have a similar class and example code available for ASP.NET, please [[contact us|http://www.synchromedia.co.uk/about-us/contact-us/]] if you're interested in that.
!No sending limit
For most self-service accounts, there is no limit on the number of messages you can send to your recipients, and it won't cost you any more to email them more often.
!Contact limits
Where we do impose limits is on the number of contacts that you can hold in your account at any one time. This may be a larger number than are on your current lists because we need to hold data on addresses that have bounced, reported spam, unsubscribed or are on suppression lists. If you go over your account limit, we will not prevent you from uploading more, nor block subscriptions to your lists, but you will not be able to send messages to your lists until you have increased your subscription level to cover your contacts - see [[Payment]] for how to do that.
!!Removing unused contacts
If you're really concerned about the number on non-subscribed contacts you have (for example if you uploaded a new 10k list and then deleted it, you would be left with 10k non-subscribed contacts eating up your allowance), we can delete them for you, though we generally won't delete those that have asked to be unsubscribed or suppressed (as opposed to those you have deleted from lists) as it would make it impossible to fulfil our data protection obligations. If after this you're still over quota, you will have to [[upgrade your subscription|Payment]].
Under the 'Settings' tab you can:
Change your password
Manage your Time Zone
Edit your company details:
* Full Address
* Web site address
* Contact email address
* Country
* Phone Number
* Fax Number
* Company logo URL
A bounce or bounceback is a message received from a mail server describing a failed delivery attempt. A typical example would be if you sent jack@example.com an email, but there's nobody called jack at example.com, so the mail server at example.com sends a message back to a special address we put in each message describing why the message couldn't be delivered. We handle all the bounces that your mailings generate, analyse them, take necessary action, and provide reports on them.

Bounces are a thorny problem for any mailing list system. Mail servers are unpredictable and very often badly configured, and you're likely to interact with several thousand different ones on a reasonable size mailing.

People often talk of 'hard' and 'soft' bounces without really knowing what they mean. In fact, hard bounces are the only ones of any real interest, and even then they are not necessarily 'hard' at all - it's all much less black and white that you might have been led to believe. Generally a hard bounce is one that is negative and likely to be permanently true, for example a reply which says 'this user does not exist'. A soft bounce is pretty much anything else, even those that describe themselves as 'permanent', 'fatal' or other such strong terms - for example a user's mailbox being full is classed as a permanent error, even though they could empty it at any moment.

When we receive a bounce message, we try to interpret what it says as accurately as possible, but it's not easy. Though there are some common standards for such messages, adherence to the rules is pretty bad. Our mail servers use a bounce processing system based on [[BoogieTools BounceStudio|http://www.boogietools.com/]]. We return the same codes we receive from their handling of bounces in the downloadable bounce reports we provide. Here's an overview of the codes:

|!Bounce Type|!Description|
|0|NON BOUNCE|
|10|HARD BOUNCE|
|20|SOFT BOUNCE - General|
|21|SOFT BOUNCE - Dns Failure|
|22|SOFT BOUNCE - Mailbox Full|
|23|SOFT BOUNCE - Message Size Too Large|
|30|BOUNCE WITH NO EMAIL ADDRESS|
|40|GENERAL BOUNCE|
|50|MAIL BLOCK - General|
|51|MAIL BLOCK - Known Spammer|
|52|MAIL BLOCK - Spam Detected|
|53|MAIL BLOCK - Attachment Detected|
|54|MAIL BLOCK - Relay Denied|
|60|AUTO REPLY|
|70|TRANSIENT BOUNCE|
|80|SUBSCRIBE REQUEST|
|90|UNSUBSCRIBE REQUEST|
|100|CHALLENGE RESPONSE|

Most of these broad categories are easy enough to understand. A non-bounce is a message that's ended up at our bounce return address that isn't a bounce, for example if a recipient sent a reply to the bounce address instead of from or replyto addresses because their mail program was misconfigured, or because a spam generator guessed lucky and created a legitimate bounce address for a spam message. For full details on what these codes mean, [[read their documentation|http://www.boogietools.com/Products/Linux/BounceStudioAPI/help/files/BounceTypes.html]].

Bounces can take time - so just because your mailshot has all been sent and you have a nice low bounce count, don't be surprised when you find that it increases later on. We've had some mail servers send us bounces 6 months after sending!

We use [[VERP|http://en.wikipedia.org/wiki/Variable_envelope_return_path]] addressing for our return path (where bounces go), so we can cope with some server misconfigurations - for example, Microsoft Exchange sometimes sends bounces that don't actually say who the original message was sent to (helpful, huh?!), but because of our addressing system, we can still figure out who it was.

Sometimes we get a bounce that says 'Uh, something didn't work' with no indication of what or why it failed, and though we try, there's not a lot we can do about such messages - it may be that the user doesn't exist, or their mailbox is full, or their mail server is just rubbish (it happens!). Sometimes mail servers just go nuts - we once had a major ISP's mail server send us 30,000 bounce messages in reply to a single message! There's only so much we can do - and all mailing list providers are in the same boat here.
!!!Greylisting
Some mail servers use [[greylisting|http://en.wikipedia.org/wiki/Greylisting]] in an often successful attempt to fool the millions of zombie ~PCs responsible for most spam into not sending them messages. This involves initially rejecting an incoming message, but allowing it to be received later on. It relies on the idea that the minimal mail senders in such programs will never get around to trying again and don't care if some of their millions of messages are not delivered. Because we run well-behaved mail servers, we have full support for this system - but be aware that it can mean that messages take longer to be delivered.
!!Automatic unsubscribe of bounces
We automatically unsubscribe consistently bouncing addresses after approximately three bounces. It's approximate because we adapt according to the historical behaviour of each address, for example if a hard bounce happens in a sequence of otherwise successful deliveries to an address, it will be ignored and future deiveries won't be affected. There is a major exception to this: Yahoo! domains (and other domains they handle, such as btinternet.com) are unsubscribed after a single hard bounce; it's a requirement of their terms of service for deliveries, and repeatedly attempting deliveries to their domains just results in delivery penalties.

Because these bounces are not dependent on content or source, we maintain them globally, so that if an address is bouncing for one of our other customers, it will be suppressed from your lists when you upload them, which helps improve your deliverability by not sending to known-bad addresses - //even on your very first send//!

We auto-unsubscribe bounces that are reported as 'unknown user', 'unknown domain', 'mailbox full' or 'bad address syntax'. It's useful to remove 'mailbox full' addresses as these days mailboxes are rarely full for real users, so they are likely to be defunct accounts that are accumulating junk, especially if they give that error consistently over several delivery attempts.
While we try to support as many different web browsers as possible, some make it very difficult, in particular Internet Explorer 6. If you use ~IE6, you may find our site slow or not particularly pretty in some places. Some browsers are over 80 times faster than ~IE6, so we highly recommend that you upgrade to a browser less than 7 years old, such as [[Internet Explorer 7|http://www.microsoft.com/windows/downloads/ie/getitnow.mspx]], [[IE8 beta |http://www.microsoft.com/windows/products/winfamily/ie/ie8/default.mspx]], [[FireFox 2.0 |http://www.mozilla-europe.org/en/products/firefox/]] or [[3.0|http://www.mozilla.com/en-US/firefox/all-beta.html]], or, for ultimate speed, standards compliance and quality, [[Opera|http://www.opera.com/]] or [[Safari|http://www.apple.com/safari/]].
As a simpler alternative to using our API, you may be well-served by our callback system. Instead of writing scripts to interrogate our system, we can tell you when something happens in your account.
This is done via a callback mechanism. On your account settings page, you provide us with the URL of a script on your site that should receive these callbacks, and we'll call it with some meaningful parameters. It's an efficient mechanism because there is only traffic generated when something happens, but at very busy times you may have a lot of requests coming your way!
Callbacks are ideal for posting events into CRM systems. For example when someone clicks on a link, it could put them into a follow-up contact queue for sales staff in your CRM.
!URL pattern
The callback URL should look like this:
{{{
http://www.example.com/callback.php
}}}
We also support https, username and password, e.g.
{{{
https://user:pass@www.example.com/callback.php
}}}
The only real restrictions are that your URL should not contain a query string (starting with ?) or anchor location/fragment part (starting with #). Of course it doesn't have to be PHP - you can use any language you like.
!Events
There are 9 callback events that we will send you:
* subscribe
* unsubscribe
* open
* click
* mailshotstarted
* mailshotcomplete
* listuploadcomplete
* listuploadfailed
* spamreport
Below you'll find descriptions of parameter names and values that will be supplied with each of these requests.
When you receive a request from us, all we would like in return is a normal {{{HTTP/1.0 200 OK}}} success response (which is the default in languages like PHP, so you don't have to do anything special). We don't log bad responses, we don't retry failed requests, and we give you 10 seconds to handle the request - it's up to you to make sure your system is available and working!
In order to reduce exposure to risk and avoid generating lots of error messages at both ends, if your url fails to deliver a {{{200 OK}}} response or fails to respond with the allotted time, the URL will be removed from your settings and no further traffic will be sent there - You have been warned! You can get and set your callback URL on the settings page or via our getcallbackurl / setcallbackurl API functions.

!!Performance issues
One omission you may notice from the event list is a callback for when we send someone a message. We're not offering this one as no CRM systems we've encountered are anywhere near fast enough to cope with the rate at which we would send them (over 200 per second). As it is some of our bigger clients get 150 requests per second for message openings alone, so please bear in mind these performance constraints when you are writing your script - for example you might want to place incoming callbacks into a queue (for example [[memcacheq|http://memcachedb.org/memcacheq/]], [[RabbitMQ|http://www.rabbitmq.com/]], [[beanstalkd|http://kr.github.com/beanstalkd/]] or [[Amazon's SQS|http://aws.amazon.com/sqs/]]) that you can process at leisure rather than trying to handle them immediately. At these peak rates, a ~MySQL instance on a shared server is unlikely to be able to process the messages fast enough. You can get a list of people that are on a list used for a particular mailshot through our web interface.
!!Subscribe
*//event//: The word 'subscribe'
*//address//: The email address that subscribed
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone)
*//listid//: The Smartmessages ID of the list they subscribed to (compatible with API functions)
*//listname//: The name of the mailing list they subscribed to (as shown on your contacts page)
!!Unsubscribe
*//event//: The word 'unsubscribe'
*//address//: The email address that unsubscribed
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone)
*//listid//: The Smartmessages ID of the list they unsubscribed from (compatible with API functions)
*//listname//: The name of the mailing list they unsubscribed from (as shown on your contacts page)
!!Open
*//event//: The word 'click'
*//address//: The email address that opened a message
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone)
*//mailshotid//: The Smartmessages ID of the mailshot the message was in (compatible with API functions)
*//mailshotname//: The name of the mailshot the message was in (as shown on your mailings page)
!!Click
*//event//: The word 'click'
*//address//: The email address that clicked
*//url//: The url they clicked
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone)
*//mailshotid//: The Smartmessages ID of the mailshot the link was in (compatible with API functions)
*//mailshotname//: The name of the mailshot the link was in (as shown on your mailings page)
!!Mailshot Started
*//event//: The word 'mailshotstarted'
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone)
*//mailshotid//: The Smartmessages ID of the mailshot (compatible with API functions)
*//mailshotname//: The name of the mailshot (as shown on your mailings page)
!!Mailshot Complete
*//event//: The word 'mailshotcomplete'
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone)
*//mailshotid//: The Smartmessages ID of the mailshot (compatible with API functions)
*//mailshotname//: The name of the mailshot (as shown on your mailings page)
!!List Upload Complete
*//event//: The word 'listuploadcomplete'
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone)
*//listid//: The Smartmessages ID of the mailing list (compatible with API functions)
*//uploadid//: The Smartmessages ID of the upload (compatible with API functions)
*//listname//: The name of the mailing list (as shown on your contacts page)
!!List Upload Failed
*//event//: The word 'listuploadfailed'
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone)
*//listid//: The Smartmessages ID of the mailing list (compatible with API functions)
*//uploadid//: The Smartmessages ID of the upload (compatible with API functions)
*//listname//: The name of the mailing list (as shown on your contacts page)
*//message//: A text message explaining why the upload failed, e.g. misnamed fields, corrupt file etc.
!!Spam Report
*//event//: The word 'spamreport'
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone)
*//address//: The email address that reported a message as spam
*//mailshotid//: The Smartmessages ID of the mailshot (compatible with API functions)
*//mailshotname//: The name of the mailshot (as shown on your mailings page)
We only receive these from a few major ISPs, however it's vitally important to the health of your lists that you remove them at source as well as in smartmessages (which happens automatically anyway).

!Example code
Here is a short PHP script to accept a callback request, apply some validation and log the incoming request as a simple tab-delimited text file:
{{{
<?php
if (!array_key_exists('event', $_REQUEST)) {
	exit;
}
$record = '';
switch($_REQUEST['event']) {
	case 'subscribe':
	case 'unsubscribe':
		if (array_key_exists('address', $_REQUEST) and array_key_exists('address', $_REQUEST) and array_key_exists('time', $_REQUEST) and array_key_exists('listid', $_REQUEST) and array_key_exists('listname', $_REQUEST) ) {
			$record .= $_REQUEST['event']."\t".
						substr(strip_tags($_REQUEST['address']), 0, 100)."\t".
						substr(preg_replace('/[^ 0-9\:-]/', '', $_REQUEST['time']), 0, 19)."\t".
						(integer)$_REQUEST['listid']."\t".
						substr(strip_tags($_REQUEST['listname']), 0, 100);
		}
		break;
		break;
	case 'click':
		if (array_key_exists('address', $_REQUEST) and array_key_exists('address', $_REQUEST) and array_key_exists('url', $_REQUEST) and array_key_exists('time', $_REQUEST) and array_key_exists('mailshotid', $_REQUEST) and array_key_exists('mailshotname', $_REQUEST) ) {
			$record .= "click\t".
						substr(strip_tags($_REQUEST['address']), 0, 100)."\t".
						substr(strip_tags($_REQUEST['url']), 0, 255)."\t".
						substr(preg_replace('/[^ 0-9\:-]/', '', $_REQUEST['time']), 0, 19)."\t".
						(integer)$_REQUEST['mailshotid']."\t".
						substr(strip_tags($_REQUEST['mailshotname']), 0, 100);
		}
		break;
	case 'open':
		if (array_key_exists('address', $_REQUEST) and array_key_exists('address', $_REQUEST) and array_key_exists('time', $_REQUEST) and array_key_exists('mailshotid', $_REQUEST) and array_key_exists('mailshotname', $_REQUEST) ) {
			$record .= "open\t".
						substr(strip_tags($_REQUEST['address']), 0, 100)."\t".
						substr(preg_replace('/[^ 0-9\:-]/', '', $_REQUEST['time']), 0, 19)."\t".
						(integer)$_REQUEST['mailshotid']."\t".
						substr(strip_tags($_REQUEST['mailshotname']), 0, 100);
		}
		break;
	case 'mailshotcomplete':
		if (array_key_exists('time', $_REQUEST) and array_key_exists('mailshotid', $_REQUEST) and array_key_exists('mailshotname', $_REQUEST) ) {
			$record .= "mailshotcomplete\t".
						substr(preg_replace('/[^ 0-9\:-]/', '', $_REQUEST['time']), 0, 19)."\t".
						(integer)$_REQUEST['mailshotid']."\t".
						substr(strip_tags($_REQUEST['mailshotname']), 0, 100);
		}
		break;
}
if (!empty($record)) {
	file_put_contents('callback.txt', $record."\n", FILE_APPEND | LOCK_EX);
}
?>
}}}
Please contact us if you have any suggestions, complaints or general comments. 

[[support@smartmessages.net|mailto:support@smartmessages.net?subject=Support Request]]

If you're a recipient who wants to be removed from a list, use the unsubscribe link in the message you received. They are there for a reason and will work far faster and more efficiently than anything we can do manually.
We offer a range of customised projects, using smartmessages at the center, and then coding in custom forms, with a complete business process from start to finish.
[[DomainKeys|http://en.wikipedia.org/wiki/Domainkeys]] and [[DKIM|http://en.wikipedia.org/wiki/DomainKeys_Identified_Mail]] (~DomainKeys Identified Mail) are anti-forgery technologies that help prevent phishing and spam, and as such increase the trust in messages that use them.
DKIM is a step beyond what [[SPF and SenderID|SPF]] can offer for forgery prevention, at the expense of some complexity. While SPF attempts to ensure that the //origin// of the message is not forged, DKIM ensures that the //content// of a message is not forged or altered, thus the two technologies complement each other nicely; DKIM is not in any way a replacement for SPF. For ultimate trust in your email, you should use both.
DKIM is a replacement for the older and less-capable ~DomainKeys, and we only implement DKIM in Smartmessages. Like SPF, it requires that you create records in your DNS server - how you achieve that will vary widely, but if you own your own domain, you should be able to access that through your registrar or DNS hosting service (incidentally, we highly recommend [[Gandi.net|http://www.gandi.net/]] for domain registration and DNS hosting).
!Why?
What follows may seem like a lot of effort, and all too complicated, so why do it? Well, since you're here, you're obviously interested in getting email in front of your audience, in their inbox, not their spam folder. DKIM can help this - although there is nothing preventing spammers from using DKIM (and some do), it means that the receiver knows that what you sent is what you meant to send, and that you are not lying about who you are (courtesy of SPF). That helps them to trust the messages they receive from you, which can, when coupled with a consistent reputation of not sending messages that are reported as spam, result in more reliable inbox placement. Some email hosts display a little icon to the user indicating that a message is from a trusted source, further enhancing trust in your subscribers.
There's another key reason: Yahoo!, one of the inventors and biggest supporters of DKIM, requires that we use DKIM if we want to receive [[spam reports|SpamReports]] about messages we send for you. ''This is the single biggest driver for improving your sending reputation, deliverability and list quality!'' Mail hosts that are known to pay significant attention to DKIM signed email include Yahoo! and Google, and more are adding it every day. It's rapidly becoming the case that ''if you don't use DKIM, you can pretty much forget about being able to deliver volume to any Yahoo! domains'', which includes some other large UK ~ISPs such as btinternet.com and talk21.com. Convinced? Read on...
!!Which domain?
When you send messages through smartmessages, you have the opportunity to enter a 'from' address, such as 'newsletter@example.com'. The DKIM records need to match the domain part (the bit after the '@', in this case 'example.com') of your from address. If you use several domains, you can create the same DNS records in each of them, and register them all in smartmessages, and we will use the right one automatically. Note that you need to have control of the DNS for the domain in question.
!!What do I need to do?
If you don't already have DKIM in your DNS, you will need to create two records, firstly a TXT record called {{{_domainkey}}} (that's an underscore character on the front of it) that contains what's called a DKIM policy. This is similar to the role of the 'all' part of an SPF record, indicating whether your DKIM keys are used for all or some of your email (and thus whether unsigned messages should be rejected or not). We suggest you start with the 'relaxed' option, which is simply:
{{{
o=~
}}}
(That's a lower case letter o, an equals sign and a tilde character). The second record you create needs to use our DKIM selector, which is {{{sm}}} for smartmessages. Selectors allows different mail sources to sign messages independently, for example by different branch offices, or (heaven forbid!) other mailing list management providers, each using their own selector.
Create another TXT record and name it {{{sm._domainkey}}}. The value of the record should be set to this:
{{{
k=rsa; p=MEwwDQYJKoZIhvcNAQEBBQADOwAwOAIxALRHPRnFUks4Hntg7AidEbw3zZGWhVXAy4Gm6TiP1Ln96IwGV1Knde4bJClKTvsGTQIDAQAB
}}}
If your DNS software complains about this value, try changing the beginning of it to {{{k=rsa\;}}}, leaving the rest unchanged.
!!How do I know it's working?
Once you've set it up, you can check it (and everything else in your DNS) is working using a service like dnsreport. If you have a Unix/Linux/~MacOS X command line handy, you can try {{{dig txt _domainkey.example.com}}} and {{{dig txt sm._domainkey.example.com}}} to check that your DNS is publishing your records correctly. Alternatively use [[this tool|http://domainkeys.sourceforge.net/policycheck.html]] for testing your policy, [[this one |http://dkimcore.org/tools/dkimrecordcheck.html]] for your selectors.
Once you've set up your DNS, you need to enter the domains you send from on the settings page of your smartmessages account. When you do so, it will check SPF and DKIM entries and confirm that they are OK. When you send correctly ~DKIM-signed messages to Yahoo! addresses recipients will see a small key-shaped icon next to your from address, indicating that it's validated.
!!!Here's one I made earlier
A complete set of DKIM and SPF DNS records for working with smartmessages will look something like this (exactly how it is presented will depend on your provider):
{{{
example.com.            10800   IN      TXT     "v=spf1 a mx include:smartmessages.net ~all"
_domainkey.example.com. 10800   IN      TXT     "o=~"
sm._domainkey.example.com. 10800 IN     TXT     "k=rsa\; p=MEwwDQYJKoZIhvcNAQEBBQADOwAwOAIxALRHPRnFUks4Hntg7AidEbw3zZGWhVXAy4Gm6TiP1Ln96IwGV1Knde4bJClKTvsGTQIDAQAB"
}}}
!!How do I register domains with smartmessages?
Once you've set up your DNS, log into your smartmessages account and go to the 'settings' tab in the 'account' page. At the bottom you will see an 'authenticated domains' section. Add your domain there and it will automatically check that your DNS contains the correct values. If you get some little red crosses instead of green ticks, double-check your DNS entries according to this guide, and you can use the 'recheck' button to try again. If you still have trouble, [[contact us|http://www.synchromedia.co.uk/about-us/contact-us/]]. Note that DNS changes can take a while to refresh (though additions are instant), so it may not give you the all-clear for several hours if you don't get it right first time.
!!How does it work?
DKIM uses [[public-key cryptography|http://en.wikipedia.org/wiki/Public_key_cryptography]], a technique which uses mathematically related public and private keys to encrypt and decrypt data. Our public key (All that random-looking text in the DNS record) is placed in //your// DNS so that when an email is received (which contains an encrypted signature created using our private key), the email server can do a DNS lookup using our {{{sm}}} selector and use the public key it finds there to verify that the email is legitimate and hasn’t been tampered with in transit. The public key needs to be in //your// DNS in order to prove that //we// are not just making it up!
!!What if I don't set up DKIM?
You don't have to use DKIM; if you don't, we will still sign the message as an intermediary, which doesn't carry nearly as much weight as your own signature. It's rapidly becoming the case that ''if you don't use DKIM, you can pretty much forget about being able to deliver volume to any Yahoo! domains'', which includes some other large UK ~ISPs such as btinternet.com and talk21.com.
[[Start here]]
This happens under the contacts tabs. All files can be opened by Excel (CVS).

[IMG[http://wiki.smartmessages.net/images/contacts.gif]]

Choose the one you want:
[IMG[http://wiki.smartmessages.net/images/downloads.gif]]
* The Edit/Upload/Download button is where you can get your complete lists.

[IMG[http://wiki.smartmessages.net/images/downup.gif]]
Several features are being considered for future releases
* Automatic pre-send [[SPF]] checks and enforcement
* Spam filter assessment of your messages prior to sending
* Dynamic list segmentation
* Always keeping an eye on developments in ~JavaScript WYSIWYG text editors to improve mailshot editing.
* Multi-language support in the customer interface
* Brandable user interface for agencies (it's already brandable for your subscribers)
* Callbacks for events (simpler and more efficient than polling our API)
[[Google Analytics|http://www.google.com/analytics/]] is a quick and easy way to add tracking for end-to-end marketing feedback. While we track all that we can (opens and clicks), we have no way of knowing how that helps your bottom line. How would you like to be able to see how many people from your mailshots actually bought something from your web site? That's the kind of thing that Google Analytics can tell you.
!How it works
When we handle a clickthrough for you (see [[Link Tracking]]), we check if the link is pointing at one of your analytics domains, we add some additional parameters to the clicked URL to let analytics know where the link came from before telling the user's browser where to go. For example, a link to //http&#58;&#47;/www.example.com/// might be extended to //https&#58;&#47;/www.example.com/?utm_source=smartmessages.net&utm_medium=email&utm_campaign=My mailshot&utm_content=12345// that is, we add in information to the link about which mailshot the click is associated with. When the browser gets to the destination site, the Google Analytics javascript spots the additional parameters on the incoming URL and adds it to the information that it logs. It then means that all activity that this particular user does can be linked to the fact that they came from the mailshot.
!How to set it up
There are two parts to setting up analytics in smartmessages. Firstly you need to go to your smartmessages accounts settings page, click the 'enable analytics' checkbox, enter the domains that you want to use analytics for (for example 'www.example.com') and then save your settings. After that, all redirected links in that domain will get the additional parameters added. Domains not in your list will not get the additional parameters. The campaign property comes from the name you give your mailshot when you send it, and the content value is our internal ID for the mailshot, which you may find useful if you use our [[API]] (or to help differentiate mailshots that have been given the same name).
The second step is to install Google Analytics on your web site. That's highly dependent on how your site is set up, but [[Google tells you how to do it|http://www.google.com/analytics/discover_analytics.html]]. Once it's done, you should find that you start to see (on the analytics site, not in smartmessages) a proportion of your visitors as coming from email links, referred by us, ripe for further analysis. It's not a real-time service, so you'll find that there is some delay before stats start coming through.
By default we track all links within a template - you don't have to do anything at all. We take your ~URLs and re-encode them so that they come via our web server using something called a redirect. This allows to track exactly who has clicked which links in which messages, but also makes your ~URLs longer.

Some email programs do not like ~URLs over 255 chars, so it's a good idea to keep your ~URLs as short as possible. For various reasons (mainly a long-standing bug in apache), we base-64 encode the ~URLs for our redirector, which adds about 37% to original URL length. We then add the unique identifier (about 32 chars) that allows us to track the message that the click happened in and add it all to the URL for the redirector. The ~URLs end up like this:

{{{https://www.smartmessages.net/v/<message identifier>_<original URL + 37%>}}}

Our overhead is thus about 64 chars, so you should be able to safely use ~URLs up to about 138 chars. That said, ~URLs longer than this will still work in many clients. We truncate ~URLs at 2048 characters before encoding - if you need them longer than that, you're probably doing something wrong!

When a message is generated for sending, we enforce [[RFC2396|http://www.faqs.org/rfcs/rfc2396.html]] section 2.4.3 compliance (the standard for URL syntax) in link ~URLs, stripping any characters that are not allowed. These are:
* All control characters (line breaks, tabs etc)
* Spaces
* Reserved delimiters: |, {, }, \, <, >, ^, ' and ".
Links in plain text messages are another matter - many plain text clients will break ~URLs over 1 line long, which is often only 72 chars. For that reason ''we don't add tracking to plain text ~URLs'' as it's more important that people get to where the link is going than that we know they have done so.

We don't track links to our unsubscribe pages (they're just not very interesting and you you can get the unsubscribe data elsewhere). If you want to exclude a link from being tracked, just add a 'nosmtracking' keyword to the link, like this:
{{{
<a href="http://www.example.com/secretclicks.php" nosmtracking>I'm not tracked!</a>
}}}
The keyword will be removed during the send process, so your recipients will never see it, the link will not go via our redirector, and it will not appear on any reports.

If you want to add further sophistication to your link tracking (for example correlating mailshot activity with completed sales), take a look at GoogleAnalytics.

See [[open tracking|Open Tracking]] for information on tracking message openings.
When you're viewing your mailing lists in the contacts tab, there's an options lurking at the bottom called mailing list arithmetic. This allows you to add and subtract the contents of mailing lists to and from one another. There are all kinds of uses for this:
*Take a snapshot of a list a a certain point in time (make a new list, add the existing list to it)
*Add members of your testing list to a newly imported list so that they receive real mailings as well as tests
*Create a list of people who were just added this month by subtracting last month's list from the current list (but make a copy first!)
Unsurprisingly, a mailing list is a list of recipients you wish to send email to. Smartmessages doesn't stop at just the lists themselves, but also allows you to gather data about your recipients, so your customers are stored once, and their subscriptions to multiple lists are stored separately. This means that if you know that fred@example.com actually likes to be called John, that fact will be available across all of your lists, not just one of them - your customer is your customer, not several different flavours of that customer. Most mailing list management services don't offer this independence, and suffer from fragmented and incomplete data as a result.

When you upload a mailing list, it is first filtered according to any active [[suppressions|SuppressionLists]] that may apply to it.

We also have some handy tricks, in particular [[MailingListArithmetic]].

At present we don't have dynamic list segmentation (e.g. mail the subset of a list that responded the last time you mailed them), but it's [[something we're working on|FutureFeatures]].
[[Start here]]
[[AccountSettings]]
[[UploadLists]]
[[DownloadLists]]
[[SendingMailings]]
[[Reporting]]
[[RepeatMailings]]
[[Payment]]
[[API]]
[[ContactUs]]

All content Copyright &copy; 2009
[[Synchromedia Limited|http://www.synchromedia.co.uk/]]
If you want to track the opening of your messages, you need to insert what's called a "web bug" or "beacon" image. This delivers a transparent 1-pixel GIF image, but also tells us exactly which message has been opened and when. When using our standard templates, you don't need to do anything, but when using your own you have a choice of two macros. Somewhere in your template, insert the {{{[[tracking_image]]}}} tag from the pop-up menu above the editor into your template, somewhere inside the body tag of your html, commonly at the bottom. You'll end up with something like this:
{{{
[[tracking_image]]
</body>
</html>
}}}
If you don't like the image tag that we generate for you, you can create your own using the {{{[[tracking_url]]}}} tag instead:
{{{
<img src="[[tracking_url]]" width="1" height="1" alt="*">
</body>
</html>
}}}
Either way, make sure that your HTML editor doesn't rewrite the tags with URL encoding as that will break the links.
!Oh no! I forgot to put a tracker in!
If you don't put an opening tracker in, the result will typically be that you get no opens shown on the reporting page. However, there is another factor that comes into play here: if we receive a clickthrough from a message that we do not have an opening logged for, we will log an open (just one) as well, as it's not possible for a click to happen from a message that was never opened - even with images turned off. If you have done this, the usual symptom is that number of reported clicks and opens will typically be very similar, whereas you would normally expect opens to be much higher than clicks.

Note that we do not attempt to support tracking opening of plain-text templates, because obviously they don't support images. Some mailing companies claim that it's possible to do this - it's not; they're lying!

See [[link tracking|Link Tracking]] for information on tracking clickthroughs.
There are two ways of paying for Smartmessages - Self-service or contract. Most of our customers take the self-service route which allows you to control your account entirely yourself. Those with more complex needs, large lists (> 100,000) or those who prefer alternative payment arrangements (such as monthly/quarterly invoice) should [[contact us|ContactUs]].

When choosing your subscription level, you should bear in mind [[what the account limits mean|Account limits and quotas]].

Click on the "Account" tab. [IMG[http://wiki.smartmessages.net/images/account.gif]]

Click on the "Buy smartmessages services" tab [IMG[http://wiki.smartmessages.net/images/smtab.gif]]

Choose the service you require, click the ~PayPal button next to the service you want. You'll be taken to ~PayPal. Either log into your account, or use the credit card payment service they offer.

Generally Smartmessages uses ~PayPal's subscription services, so your payments will happen automatically every month without you having to do anything.

Phishing attempts to trick you into revealing your personal and financial details, often by making web sites that pretend to be sites such as eBay, Paypal and banks, but it can occur for any site that typically asks for your details.

Smartmessages includes support for anti-phishing measures. We provide an opportunity for our customers to include a link back to us, and we use that link wherever we ask for your details, so you can check that we are legitimately acting for a customer, and not attempting to obtain your data for nefarious purposes.

To be safe from phishing, you should check that email messages really come from where they say they do, and that any domain name (the 'example.com' part of 'user@example.com') used in an email is the same as the anti-phishing page our customer has posted.

This service is optional for our customers and if you want such assurance, you should ask them to provide us with an anti-phishing page.
The quickest way to send a new mailshot that's similar to one you've done before is to make a copy and edit it, for example to send this month's newsletter, you might copy last month's and edit it. This can save quite a bit of work.

Choose the mailings tab: [IMG[http://wiki.smartmessages.net/images/mailings.gif]]

Click the copy button for the mailing you wish to use as the basis for next mailing. [IMG[http://wiki.smartmessages.net/images/mailings2.gif]]

Click the Edit button for the new mailshot.

This will take you to the send page populated with the details from the original mailing.
Click on the mailings tab: [IMG[http://wiki.smartmessages.net/images/mailings.gif]]

Click on the name of the mailing or a report button to see results.

Alternatively, click on the reports tab: [IMG[http://wiki.smartmessages.net/images/reports.gif]]

See the last viewed results, choose the required mailing from the popup list. View results.
SPF is the [[Sender Policy Framework|http://www.openspf.org/]], a mechanism used for preventing forgery of from addresses in email, and because of its strength in proving you are who you say you are, improves deliverability as filters are less likely to think that you are sending spam or phishing emails (and conversely, if you are sending spam, they can block you more effectively). It's an increasingly important weapon in the war against spam, it's used by most of the big email providers (AOL, Hotmail/MSN/Windows Live, Yahoo!, ~GMail, etc) and we recommend full support for it.
!!How does it work?
When you send a message through smartmessages, it will be sent by one of our mail servers. Normally, there's nothing to confirm that we're not just pretending to send legitimate messages from you, and because of that, servers receiving these messages may treat them with suspicion. You can fix this by naming us as a source of email for your domain in an SPF record, which is part of your domain name (DNS) setup. Read the [[OpenSPF site|http://www.openspf.org/]] for info on how to do that - the key thing is that you should add us to your SPF record, which will allow us to send mail from your domain.
!!The technical bit
Read the [[OpenSPF|http://www.openspf.org/]] docs and/or use their wizard to create an appropriate SPF string, then insert it into your DNS as a TXT record.
A fail-safe SPF record that includes us is:
{{{
v=spf1 a mx include:smartmessages.net ?all
}}}
This translates to: //Explicitly allow sending from this domain, its mail servers and smartmessages. For everyone else, give a neutral response.// Ideally you should aim for a '-all' (default to 'fail' rather than 'neutral' status), but don't set that until you're sure you have all your mail sources covered.
Once you've set it up, you can check it (and everything else in your DNS) is working using a service like [[dnsreport|http://dnsreport.com/]]. If you have a Unix/Linux/~MacOS X command line handy, you can try {{{dig txt example.com}}} to check that your DNS is publishing your record correctly.
You can do SPF lookups [[here|http://www.openspf.org/Why?showform=1]]. Enter one of our IP addresses (e.g. {{{93.93.128.140}}}) and your proposed from address. Ideally you want a 'Pass' result, though 'Neutral' will work. If you get a 'Fail' or 'Softfail' response, we will not be able to send from that address reliably for you.
If you want to be an especially good citizen in your SPF records, it's nice to provide IP addresses rather than hostnames as it saves the receiving mail server a DNS lookup. For example instead of 'a' or 'a:www.example.com', specify the actual IP, like 'ip4:123.123.123.123'. The terms in an SPF record are evaluated left to right, so put the most likely matches first. You can do similar things for your MX record, though if you use a commercial incoming mail service like messagelabs, we suggest you stick with a regular 'mx' rather than enumerating their ~IPs.
We recommend that you don't enumerate our server ~IPs in your SPF, but use the include delegation we suggest as then we'll retain the ability to reconfigure our own servers without having to bother you with updates. Our own SPF uses a '-all' default, so we don't represent a back-door to neutral responses.
!!Are there any downsides?
One in particular: If you commonly send email through your ISP or web mail provider using your own domain as the from address (i.e. you are in the habit of forging your own address!), you have three options:
#Use the '?all' default action (which doesn't do anything for spam prevention)
#Include the ~IPs of your ~ISPs mail servers (they should be able to supply them, but it means that anyone else at your ISP can forge mail from you)
#Alter your sending settings so you only send through your own mail servers (the most effective, but least flexible way). If your ISP blocks or redirect SMTP traffic on port 25, you may be able to get to your mail server using a submission port which is typically on port 587 and tends not to get blocked.
!!What about ~SenderID?
[[SenderID|http://www.microsoft.com/mscorp/safety/technologies/senderid/default.mspx]] is a Microsoft-backed extension of SPF. Though it has some [[well documented pitfalls|http://www.openspf.org/SPF_vs_Sender_ID]], they are easily avoided, and it's worthwhile implementing it because hotmail (and related sites such as MSN and live.com) uses it, which is a good proportion of most ~B2C mailing lists. The most straightforward way to implement ~SenderID is to set up your SPF record and then delegate to it. This way you will only have one record to maintain (your SPF) to identify your legitimate mail sources. To do this, create another TXT record containing this text:
{{{
spf2.0/pra ?all
}}}
And that's it. Having done this, you should [[register your use of SenderID|https://support.msn.com/eform.aspx?productKey=senderid&page=support_senderid_options_form_byemail&ct=eformts]] on Microsoft's site to ensure they use it.
!!What about ~DomainKeys and DKIM?
While SPF helps to increase trust that a message's //origin// is where it says it is, DKIM and Domainkeys serve to show that a message's //content// has not been altered in transit, so the two go hand-in-hand. The way it works is fairly complex (using public-key cryptographic signatures), however the practicalities are quite straightforward. If you're already altering your DNS to add our SPF, then we thoroughly recommend that you set up DKIM as well. [[Read our guide|DKIM and DomainKeys]] on what it means and how to do it.
!!Example of a forgery rejection
Someone on the Turkish ~MarsNet DSL service attempted to send a message that claimed it was sent from our own mail server. Not surprisingly, when an SPF check was done by a Turk Telecom mail server (thank you Turk Telecom!), the message was rejected because our SPF record correctly identified it as a forgery. You can see that amongst the headers is a link to a page which will explain why the message was rejected. This is absolutely what SPF is intended to achieve, and here you can see it working perfectly.
{{{
This is an informative message sent by mail.atamedya.com.
The server was not able to deliver your email message to the following addresses:

 <sales@synchromedia.co.uk> (mail.synchromedia.co.uk: 550 See http://spf.pobox.com/why.html?sender=postmaster@synchromedia.co.uk&ip=77.92.158.139&receiver=mail.synchromedia.co.uk (#5.7.1))Reporting-MTA: dns; mail.atamedya.com
Arrival-Date: Thu, 16 Jul 2009 12:01:44 +0300

Final-Recipient: rfc822;sales@synchromedia.co.uk
Action: failed
Status: 5.1.1
Remote-MTA: mail.synchromedia.co.uk
Diagnostic-Code: SMTP; 550 See http://spf.pobox.com/why.html?sender=postmaster@synchromedia.co.uk&ip=77.92.158.139&receiver=mail.synchromedia.co.uk (#5.7.1)
Received: from synchromedia.co.uk ([81.215.222.134])
	by mail.atamedya.com (Kerio MailServer 6.1.4)
	for sales@synchromedia.co.uk;
	Thu, 16 Jul 2009 12:01:42 +0300
From: "Post Office" <postmaster@synchromedia.co.uk>
To: sales@synchromedia.co.uk
Subject: 
Date: Thu, 16 Jul 2009 12:01:11 +0300
MIME-Version: 1.0
Content-Type: multipart/mixed;
	boundary="----=_NextPart_000_0014_D23B030D.A4D8B533"
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 6.00.2600.0000
X-MIMEOLE: Produced By Microsoft MimeOLE V6.00.2600.0000
}}}
We are very aware that we are holding your precious data, so we ensure that your data is safe as far as we can:
!!SSL encryption
We use secure connections whenever you're viewing our site (look out for a little padlock in your browser) - this means that all ~URLs, data (e.g. your lists), pages, cookies are safely away from anyone eavesdropping on the connection between us. Any site that doesn't do this is bordering on breaking the data protection act (though not quite breaking it, yet). Our mail servers use SSL too, so the messages we send out are also safe from prying eyes while in transit, so long as the recipients mail servers support it too.
!!Make no attempt to hide
All our internet addresses resolve properly both forwards and backwards, and they change only very rarely (for example when we use a new ISP or add new servers) - we don't try to hide our servers because we don't send spam.
!!SPF support
All the mail we send in our own name uses our [[SPF]] record (which is set as strict as it can be) so recipients can be sure that we sent it, not someone pretending to be us.
!!Our code
We follow best practices when it comes to writing secure code. We have defences against SQL and header injection attacks (about the most common kind) amongst others, and our servers are always up to date with the latest security patches.
Generally, we don't run other web apps (e.g. forums, blogs, ~CMSs etc) on our cluster (for example this wiki is not on it), so we're immune to security holes in such packages.
!!Viruses, trojans etc
We don't scan outgoing messages for two reasons. Firstly, we generate every message from scratch - we never forward anything from others, and we don't allow attachments or ~JavaScript in our messages, eliminating the most common infection vectors. Secondly, we don't run Windows (on desktops or servers), where 99% of security threats are found.
!!Backups
We take backups every night, so we guarantee to have a backup of all your data up to that age. Beyond that your data is your responsibility - you can download a copy from us any time you like.
!!Redundancy
Smartmessages runs on a cluster of redundant servers, allowing hot failover should one fail. All critical systems reside on RAID volumes and use redundant power supplies, so we're immune to the most common kinds of hardware failures.
!!Physical security
We host at ~RedBus in London's docklands, one of the UK's premier hosting locations, featuring clean, reliable power supplies, overspecified air conditioning, heavy physical security (retinal scanners etc).
!!But that's not the end of the story...
It's your data we're trying to keep safe, so you can help too. Implement [[SPF]] for your own domain names and add us to your list of permitted email sources. Make use of our [[anti-phishing|Phishing]] features, especially if you are collecting data from you recipients through any of our services.

"Send to a friend" is a feature whereby having received a message from us, you feel you might like to forward it to a friend, and rather than using your email program's forward facility, you come to our site and fill in a form that sends your friend a copy of a message. Sounds like a good idea, but it has numerous hidden pitfalls.
!!Our solution
We provide a simple forwarding approach that has none of the downsides of the "traditional" approach: We provide a link that creates an email message in the user's usual email program, pre-populated with a link to the web version of the original message. This way:
* The message is sent directly from the recipient to the friend - we're not involved at all.
* It's instant and very easy to use - no logins, no web forms required
* The friend gets to see your message in full, with none of the original recipient's personalisation, and guaranteed free of any problems introduced by the original recipients own email service or program (many such programs corrupt or "constructively rewrite" forwarded messages).
!!What's wrong with the original way?
* It's very unlikely to be used. When reading an email you want to forward, your first reaction is to use your normal "forward" command, not one built in to the message.
* The person who receives the message effectively receives an unsolicited message from us. That's borderline legal in the UK, but in many countries it's an imprisonable offence (for example in Germany and Spain). Since it is us that is doing the sending, we're not too happy about that.
* For compliance with data protection laws (including in the UK), we have no rights to, and thus can hold no data about the friend that you sent the message to - we must discard everything, so this operation has zero value for collecting leads.
* Any unsolicited message is much more likely to be reported as spam, which when considered globally is likely to negatively impact the deliverability of ALL of your other mailings, including those for which you have full opt-in permission.
* If we pretend that you are the sender (e.g. by putting your address in the from field), we will be spotted as a fake, your message may well be rejected by any receiver that implements SPF (as we recommend), and you're even more likely to be reported as spam.
* In order to provide a web page where you could do this safely, you would need to log in to our site. If we didn't do this, we would be providing a spam gateway.
* It's not all down to you - we send message for all kinds of companies, and allowing it for one could reduce the deliverability of ALL those that use smartmessages, including you.
* It's not permissible under Goodmail compliance, which is something we're aiming for (which gets better deliverability for everyone).
Does it still sound like a good idea? Even if we did provide this service, the one and only benefit you could possibly derive is a very small increase in the number of people that you know have viewed your message. Say 0.5% of recipients (being generous!) forward the message by this route. Perhaps half of those might arrive unaffected by filters (because of their forged origin), and of those that do, 75% of them might actually be read (the one upside of supposedly being from a friend!). All that effort represents a possible 0.18% increase in opening stats, something that could easily be wiped out by a single spam report.
!!How fast does sending go?
Rates vary because of many factors, but you should expect rates around the 220,000 messages/hour mark. We are working on improving this all the time. Factors affecting send rates include:
* Size and complexity of your template
* Size of your list
* Activities of other smartmessages users
* Distribution of recipients (e.g. sending all to one ISP may be slower).
Lists of over about 16,000 recipients will get the highest send rates as over that size mailings can take best advantage of our sending cluster.
Should you have particular performance requirements beyond this, we can add servers to improve throughput at any time.
!!Why wouldn't I want it to go faster?
There is a large negative associated with a high send rate - it may adversely affect your delivery success rate. Many large ~ISPs (Yahoo!, Googlemail, AOL, MSN etc) impose restrictions on how many messages may be sent from one location in a given amount of time, or the frequency with which you send messages to specific users. They don't explicitly tell you that they are doing this, or let you know what their limits are, but you'll find that you'll get increasingly large numbers of bounces with a "4.4.1 Deferred Delivery" code. This code means that they may accept the message at some unspecified time in the future. Our mail server will retry delivery and progressively fall back with longer and longer times until it just gives up, typically after 4-7 days.
1 - Choose message template:
*Standard and Custom templates.

2 - Choose who to send it to:
*Send to a single email or a mailing list
*Add a salutation for single emails (if included in the template)

3 - What are you sending:
*Enter your subject or leave the defualt.
*Insert your new content here (text/image/links)

4 - Who is sending?
*from address
*from name
*reply-to address (if empty the from address is used)
If left empty the current user's address is used.
When setting your from address, please take heed of [[SPF]] as it will affect your delivery rates.

5 - Campaign Management
*Name the mailshot
*Store the mailshot in the campaign of choice

6 - Ready to send?
*Preview what is to be sent.
*Save it for future editing
(To reopen it after saving, go to mailings and click the edit button of the saved mailshot).
*Send now or schedule for a future date.
Help and tips for your Smartmessages.net account
Smartmessages Help
If a recipient receives a message they don't want, they often have two choices: unsubscribe from the list, or report the message as spam. All of our messages contain a working [[unsubscribe link|Unsubscribes]], and we also populate the "~List-Unsubscribe" header, making it as easy as possible for recipients to remove themselves from lists, however, some will still click the "report as spam" button. Most of the time this is not very helpful - it often won't stop them receiving messages because we don't get to find out about it (unlike unsubscribes), and it can adversely affect the delivery to those who do wish to receive them. Fortunately there is a little light at the end of the tunnel - some ~ISPs provide spam report data whenever someone reports a message as spam. Unfortunately, some don't do it at all, and some make it difficult to receive such messages. AOL is a shining example of how to do it right - not only do they provide the reports with a minimum of fuss, but they are in a format (Defined by an open standard - [[RFC 3462|http://www.faqs.org/rfcs/rfc3462.html]]) that's easy for us to process automatically. When other ~ISPs see the light, we will add them to our spam report handler.
Yahoo! requires that you use [[DKIM|DKIM and DomainKeys]] in order to receive spam reports.
!!What happens when we receive a spam report?
For the ~ISPs that we receive reports from, we process spam reports automatically, as soon as they are received. The address that the original message was sent to is unsubscribed from all lists within the account that the spam reported message was sent from, and a block is placed on that address so that no messages will ever be sent there again - a spam report has such bad consequences for deliverability that it's simply not worth risking them for the sake of a single address. The address will be suppressed from any subsequent list uploads and prevented from subscribing in future. Until the market recovers from the damage caused by the "never click an unsubscribe link" myth, we have little choice in this approach. 
!Welcome to Smartmessages Help

This is here to help you to use our service as easily as possible. Anything else you need help with? [[Ask us|ContactUs]]!

There are several parts to email marketing:
*What you send - [[Templates]]
*Who you send it to - [[MailingLists]]
*When you send it - [[SendingMailings]]
*What happened after you sent it - [[Reporting]]
Smartmessages supports these key functions for you.

Have a browse around this ~TiddlyWiki - click some of the topics on the right - they will appear in this middle area.
[[TiddlyWiki guide|http://www.giffmex.org/twfortherestofus.html]]
There are several ways that people can subscribe to your lists. On the contacts page you'll see a list of your mailing lists, and each one has a "Link" link which will take you to a subscribe page for that list, for example https://www.smartmessages.net/subscribe/1886. If you want to add a simple subscribe link to your own pages, you should use whichever of those links is appropriate. The default form captures just the email address and a single-field name. If you want more than that, you can build your own form.
!!Custom signup forms
Many of our customers want to use their own web forms to submit information to our subscription processor, and that's also easy to do - just point your form's action at https&#58;&#47;/www.smartmessages.net/subscribe.php. The form processor can make use of the following fields (bold fields are required):
*''//command//'' - the value 'subscribe'
*''//emailaddress//'' - the email address of the new subscriber
*''//mlid//'' - the ID of the mailing list they are subscribing to (this is the value that's visible in the "link" links on the contacts page)
*//title// - 'Mr', 'Miss', 'Dr.', 'Herr' etc.
*//dear// - a straightforward single-field name that actually corresponds with our 'dear' field
*//firstname// - the subscriber's first name
*//lastname// - the subscriber's last name
*//companyname// - the subscriber's company name
*//postcode// - the subscriber's postcode
*//language// - the subscriber's preferred language (2-character ISO 639-1 code, e.g. 'en', 'fr', 'de', defaults to 'en')
*//country// - the subscriber's country (2-character ISO 3166 code e.g. 'GB', 'FR', 'DE', defaults to 'GB')
*//redirect// - a URL to go to after processing the subscription request instead of displaying our own default page (don't forget to ~URL-encode it)
*//json// - any value - its presence will indicate that you want a response in a JSON format (i.e. you're subscribing from ~JavaScript)
By building your own form and providing a redirect URL, you can use our subscribe processor completely transparently and invisibly to your users. If you specify a redirect URL, you will receive an HTTP GET request to that URL containing your submitted parameters (so you can process it further - for example add it to your own contact database) along with additional information about the success (or not) of the subscription request in a 'statuscode' parameter. This has the following meanings:
*1 - Success
*2 - Already subscribed
*3 - Internal error
*4 - Missing required parameters
*5 - Invalid email address
*6 - Invalid mailing list ID
The JSON output also includes a 'success' value that is true for codes 1 and 2, false for others, along with a 'message' value containing a plain-text explanation of the response.
!!Landing page
Every smartmessages account gets to use our simple landing page which includes data capture of all standard fields and the option to subscribe to all mailing lists that are marked as visible. You'll find the link to your landing page on the front page after you log into smartmessages.
!!API
If you are undertaking more complex integrations (for example capturing custom fields or a full postal address) then you will be better served by the subscribe and setUserInfo functions in our [[API]].
A suppression list is an "anti-mailing list" - a list of people that you do NOT want to mail.

We maintain several different kinds of suppression list:
*Unsubscribes
*Suppressions
*Spam reporters
*Persistent bouncers
When someone unsubscribes from one of your lists, they are attached to the suppression list for that list alone, that is it will ''not'' apply to any of your other mailing lists.

Similarly, when you upload a suppression list, it only applies to the list you uploaded it against.

[[Spam reporters|SpamReports]] are applied across your whole account, to all your mailing lists, so if someone reports one of your messages as spam, they will be removed from all your lists and prevented from being uploaded to all mailing lists in future. The small increase in delivery count you might get from persisting with such recipients is far outweighed by the negative impact it can have on your deliverability to everybody else. You can download a list of the people who have reported your messages as spam on the contact page.

Persistently bouncing addresses are the only thing we share across all accounts, so you can benefit from some level of list cleaning simply by uploading your list before you have sent anything, just because one of our other customers may already have ascertained that some addresses bounce persistently. This bounce list is not available for download.

When you do a list upload, all addresses that match any of these suppressions are removed before they are added to your list.
Some of our customers want to integrate their mailings with surveys using services like [[SurveyMonkey|http://www.surveymonkey.com/]] and packages like [[LimeSurvey|http://www.limesurvey.org/]]. Here are some integration notes.
!!~SurveyMonkey
~SurveyMonkey doesn't preload lists of potential respondents, instead it relies on collecting details of those that do respond. This means that they can't prevent unauthorised people accessing the survey, and also that they can't offer any data pre-population or personalisation. On the upside, it also means there is very little setup required. To connect smartmessages messages to a survey, you need to use their [[web collector integration|http://www.surveymonkey.com/HelpCenter/Answer.aspx?HelpID=343]], and you'll generate ~URLs to feed into it using our template editor. You need to start with a link to the anonymous survey entry point and add a unique identifier for each recipient - their email address will do nicely. So a base URL for your survey (obtained through your ~SurveyMonkey account interface) that you link to from your message template might be:
{{{
http://www.surveymonkey.com/s.aspx?sm=v8MbvURxoHkWfvud7Or3Cg_3d_3d
}}}
You then need to add a 'c' paramater to it like this:
{{{
http://www.surveymonkey.com/s.aspx?sm=v8MbvURxoHkWfvud7Or3Cg_3d_3d&c=[[email]]
}}}
That code will expand to the recipient's email address
After your survey is complete you can download the results from ~SurveyMonkey.
For those that like to know such things, here is some technical background on Smartmessages.
* Built in OO ~PHP5, around 60,000 lines, excluding libraries
* Message generation using [[PHPMailer|http://phpmailer.worxware.com/]] (of which we are one of the maintainers)
* Tested with ~SimpleTest
* Templates (for both site and messages) with Smarty
* ~MySQL 5 database cluster
* Memcached distributed cache
* Run on Ubuntu Linux, on dual- and quad-core servers
* Cluster deployment for scalability and redundancy (using linux-ha) - we can add more servers to increase speed as needed
* Sharedance for persistent distributed, redundant session storage
* ~FCKEditor x-browser WYSIWYG editor
* Last and definitely not least, ~GreenArrow qmail-based mail servers, capable of > 1million messages/hour per server!
We have recently enabled user-uploadable templates so you can paste in your template, or grab it from a web page. These templates can make use of some (but not all) of our dynamic reusability features.

//Please note: unlike other sites, you don't necessarily need to use this feature. Our standard templates provide straightforward WYSIWGYG editing without any HTML authoring required. You only need to use this feature if you're familiar with HTML email and want to code your own.//

The templates tab allows you to add a new template, then add your contents. You can provide both HTML and plain-text versions, which you can grab from ~URLs if you happen to have posted your templates on a web server somewhere, though be aware that the web and email are really quite different, and most web pages will simply not work as email.
!!On the templates page...
You'll see a list of your templates (which will initially be empty) on the left hand side - click the 'Add' button below the list to create a new template.
Each template can have a title (which will appear in menus and informational screens, such as the mailings tab). The description is used on the send page to provide a longer description of that particular template's features or purpose.
If you check the 'Editable body section' checkbox, you will see an HTML editor when you go into the send page and select the template. This allows you to re-use templates, rather than having to define a new one every time. In order to make use of this, your template must include a {{{[[body]]}}} tag, which will be replaced with the contents of the send page editor.

The subject line is a default and may be overridden on the send page (and you can use the same syntax for field insertion in the subject as in the HTML and plain text bodies, though bear in mind that HTML tags won't work.
!!Dynamic fields and macros
Each editor panel has a pop-up menu containing various dynamic fields and macros that you can insert into your templates. These range from simple tags like {{{[[firstname]]}}} to more complex macros like {{{[[formal_greeting|default]]}}}.
!!!Greeting your recipient
The greeting macros dynamically create a suitable greeting string. Given data 'Mr', 'John' Smith' in 'title', 'firstname', and 'lastname' fields, {{{[[formal_greeting]]}}} would result in 'Mr Smith', and {{{[[informal_greeting]]}}} would give 'John'. If you had a 'dear' field containing 'Johnny', that would be used in preference in both cases. If you lack appropriate data to generate a suitable greeting, it will fall back to whatever default you specify in the tag. A typical example in your template might be:

Dear {{{[[informal_greeting|Subscriber]]}}},

The text after the '|' character (that's a 'pipe', not a letter l or I), in this case 'Subscriber', is used when you don't have any suitable personalisation fields.

''Note that this syntax for a default value applies ONLY to these greeting fields, not any others''.
!!!Tracking openings
For your message openings to be tracked, ensure that you include the {{{[[tracking_image]]}}} macro. This expands to a transparent 1-pixel GIF that includes tracking information in its URL. See [[open tracking|Open Tracking]] for more information on tracking message openings. If you don't put this in, we automatically add one for you, just before the closing body tag.
!!!Unsubscribe
For your subscribers to be able to remove themselves from your lists, the {{{[[unsubscribe_link]]}}} generates a simple unsubscribe link with the work 'unsubscribe'. If you want to make your own link, you can use {{{[[unsubscribe_url]]}}} in your own href instead.
To conform to our terms and conditions and data protection / anti-spam laws, ''you MUST include one of these links''. If you do not include one of these options, we will insert one automatically at the bottom of your template, just inside the closing body tag.
!!!Web version
For clients that end up with unreadable messages, or those with plain text email readers, you can include a link to a generic (no personal info, because it's public) version of your mailing using the {{{[[webversion_url]]}}} or {{{[[webversion_link]]}}}.
Note that web versions will suppress the appearance of unsubscribe and web version links, since they are meaningless and confusing in that context.
!!!Unique ~IDs
Sometimes you need a unique ID to prevent caching (a.k.a. a "cachebuster") or provide unique links into an ad tracking system etc. We provide two different kinds of unique ID in the template editor: {{{[[unique_message_id]]}}}, and {{{[[unique_recipient_id]]}}}. The difference is that every message sent to every recipient will have a different unique message ID, but every message sent to the same person will have the same recipient ID. The ~IDs themselves are standard 32-character ~MD5 hashes. Which one is appropriate for your application will be up to you, but generally you should only need {{{[[unique_recipient_id]]}}}. You could use the recipient's email address as a unique recipient id using {{{[[emailaddress]]}}}.
A template provides the overall look and layout of the content of the messages you send through smartmessages.
Out of the box, we provide some standard basic templates for a blank message (you provide all content), a simple note, an invitation to an event, and a newsletter. These are ready to roll, and if you have paid for our account setup service, you'll find these automatically make use of your custom headers and footers. Each template can contain multiple editable elements - a simple note has a single content area, but a newsletter has four, and the send page will automatically show the options to match the template.
These templates also include a plain text version, an automatic link to a web version (for those who can't or have trouble receiving HTML email), a link to subscription options (unsubscribe etc), and an opening tracking image.
!!What's special about Smartmessages templates?
The big difference between our templates and those of most other providers is that they can be reused. Instead of having a designer create a new template for you every month, you can get them to do it just once, and then you can just change the content every month without having to go back to your designer every time. We feel that anything less doesn't really justify the name 'template' - why go to all that effort and testing for a single mailing?
We can build custom templates for you from scratch, or you can provide us with your version and we can adapt it for you, or you can do it all yourself through our [[templates|TemplateUploads]] page, at your own risk of course.
!!Creating your own templates
If you're creating your own templates using our templates page, there are some things you need to be aware of when designing HTML for email.
!!!Email is not the web
Many people forget this and expect HTML email to act just like a web page. It won't. Here are some things you need to look out for:
* ''Old-school HTML 4 rules''. With the recent ravages of MS Outlook 2007, CSS in email is now mainly a recipe for disaster. While there are still ways you can use it, it's so convoluted to make it work reliably that it's not really worth the hassle. This means that you should dust off those old articles about sliced images, tables for layout and font tags - they are the only things that work reliably and easily. Email now is like the web was in 1997.
* ''All ~URLs must be absolute'' - if your links or images don't start with 'http', they are probably wrong. On a web page these ~URLs are considered relative to the current page, but when you're looking at an email, the message doesn't have a URL, so those ~URLs will not work.
* ''No external resources'' - that means no external scripts or style sheets.
* ''Don't use the <base> tag'' - it can work, but will also break in some clients (hotmail), and will prevent you from using intra-page links (href="#...").
* ''No text over images''. One of Outlook 2007's most heinous acts is to make it impossible to place text on top of images because table cell backgrounds don't work in it.
* ''Web pages are not email messages''. The majority of web pages presented directly as emails simply won't work, so don't expect them to.
* ''Imported templates are filtered'' before use. If we didn't filter javascript and various other aspects, we could become a vector for [[XSS attacks|http://en.wikipedia.org/wiki/Cross-site_scripting]].
In order to work within these restrictions, we have some other suggestions which are mainly just good practice for web, email and informational design:
* ''Validate your HTML'': Invalid HTML is just wrong, no exceptions - if you have cross-client layout problems, check the HTML is valid first - The [[Total Validator|https://addons.mozilla.org/firefox/addon/2318]] plugin for Firefox is a good tool for this, or paste a rendered message (our web preview is a good source for this) into the [[W3C validator|http://validator.w3.org/]].
* Make sure your message remains meaningful and legible with images disabled since that's the default in the majority of email clients. //Always// use alt attributes on your images, and make them meaningful as they often displayed when images are off.
* ''Keep it simple'' - email clients are not modern browsers; keep your stories short and messages clear, link to more complex content (clicks are your marketing intelligence goldmine). Smaller, simpler messages send faster, bounce less, open faster, dilute recipients precious attention less.
* Provide a plain text version of your template - some users //like// living in the last century...
* Use background colours to add colour to your messages when there are no images.
* ''TEST, TEST, TEST'' in all email clients you expect your message to be read in - you'll probably need yahoo, hotmail, gmail accounts, and Outlook 2003, Outlook 2007, Apple Mail, Eudora, Evolution and Thunderbird desktop clients. Alternatively, use a service like [[Litmus|http://www.litmusapp.com]] for cross-client testing.
* You don't have to do anything special to get your links tracked - just leave them as they are. You can also [[suppress link tracking|Link Tracking]] on a per-link basis.
* To insert dynamic data within your templates, use the macros available in the template editor pop-up.
* If you stick to straightforward HTML with no javascript and no external references (other than images), you shouldn't run into any issues with filtering.
!![[The Daily Telegraph|http://www.telegraph.co.uk/]]
We recently undertook a data protection and list cleaning exercise for the Daily Telegraph for their list of two million readers.
!!Daily Telegraph Fantasy Football
We ran last season's fantasy football mailings to their list of 200,000.
!![[Guitar Amp & Keyboard|http://www.guitarampkeyboard.com/]]
One of Europe's biggest music retailers, we handle their list of 140,000
!![[Woolovers|http://www.woolovers.com/]]
A small business that got some great results:
//"The broadcast of the email started at just after 9pm last night finishing around 10.45pm.
Number of sales for both today and yesterday 142 & 102 just for today. If you look at the same time period for last week we only had 31 orders for the two days. A big success so far.  Let’s see how more orders flow through over the weekend. A big thank you to all of you for the help you gave me in setting this fantastic marketing tool up."//
To comply with all the data protection laws, including the US ~CAN-SPAM act, It's vital that every message sent to a list includes an unsubscribe link.

You might think that the last thing you want is to make it easy for someone to get off your list, but there are major advantages (quite apart from your legal obligations) to doing so. Put it like this - every time someone unsubscribes, the quality of your list goes up; it contains proportionally less people that don't want to hear from you. If you persist in sending messages to someone that doesn't want them, they will most probably [[report your message as spam|SpamReports]], which can reduce the deliverability of ALL your other messages, or even get you blacklisted/blocked in the worst case. That's not good. It's also not polite, so do what your subscribers ask.

All our standard templates include an unsubscribe link, and you can add them to your own templates in our [[template editor|TemplateUploads]].

Because links can sometimes go astray or become corrupted within the body of a message by mail/spam filters, we include something called a "~List-Unsubscribe" header in every message, as described [[here|http://www.list-unsubscribe.com/]] and in [[RFC 2369|http://www.faqs.org/rfcs/rfc2369.html]]. These provide a simple and consistent way for subscribers to remove themselves from your lists, are much more likely to make it through filters intact, and are supported by an increasing number of the major email services, most notably Windows Live Mail, Gmail and Yahoo!

We always process unsubscribes immediately - if you have a mailshot scheduled to send and someone unsubscribes 1 second before it is sent, they will not be mailed.

You can get a list of users that have unsubscribed from each of your lists on our contacts page - just click the 'Download Unsubscribes' button to get a simple CSV format list. If you maintain a list of subscribers outside of Smartmessages, you can use that list to remove those that have unsubscribed.

When someone unsubscribes themselves from a list, we automatically [[suppress|SuppressionLists]] them from uploads to that list so that they do not get inadvertently re-subscribed against their wishes.
This happens under the contacts tabs.

[IMG[http://wiki.smartmessages.net/images/contacts.gif]]

Choose the Edit/Upload/Download button:
[IMG[http://wiki.smartmessages.net/images/downloads1.gif]]

[IMG[http://wiki.smartmessages.net/images/updown.gif]]

When uploading a list there are some options.
!!Source
It's important to be able to keep track of where the email addresses in your account came from, so when you fill this field in, anyone who is added to a list will have this note attached to their history.
!!Overwrite existing data
When you add someone to a list, there are three scenarios:
* They are already on this list
* They are not on this list, but they are on other lists of yours, or have been in the past
* They are new, and you've never seen them before
The first case is simple - we do nothing, leaving their data untouched. In the second case we add them to this list, but don't touch any of their other data. In the third case, we simply add all the data you upload attached to the new address.
Now imagine that the data that is already in the system is wrong, or outdated and you want to replace what's there. For example if you have live data in custom fields that is used every week, you would want to check this box, similarly if you uploaded data that was incorrect (e.g. you got firstname and lastname the wrong way around).
!!Replace existing list
Normally a list upload only adds to a list. If you check this box, anyone not included in the list you upload will be removed. So if there are 10,000 subscribers on this list and you upload a list of 10 new ones and check this box, you will end up with a list with only 10 people on it - so tread carefully!