4
SendMessage API Example
Question asked by Alphonse Giambrone - 1/25/2021 at 3:22 PM
Answered
I've seen this posted before, but thought I'd try again. It seems that SmarterMail support doesn't include API support.
Could someone please post a sample of using the SendMessage API? 
Preferably in .NET. 
Including how to attach a file would be really awesome!

10 Replies

Reply to Thread
0
ilanmazuz Replied
Hi Alphonse, did you find the answer to this? i am struggling with it now myself, also using C#.

Thanks,
ilan.

0
Alphonse Giambrone Replied
Yes, I did, however, it is work product belonging to the client, so can't share the code. I used HTTPClient. The way to figure it out is to use Fiddler. Start up Fiddler, then log on to smarter mail via your browser. Capture the login exchange and duplicate that. Once that is working, Send a simple message, capture that exchange and duplicate it.
Attaching files is a multi-step process, so do that last. As I recall, there were some quirks with that, so when you get that far i can probably find them and help out.
0
ilanmazuz Replied
Thanks for the reply man, i appreciate it.
i actually got stuck with an error when i tried to send, it says that something is missing in my payload, so using Fiddler to capture what the payload that smarter mail is using sounds good. i will try it out.

Thanks a lot for wanting to help, i will reach out if i'll need something specific.

0
Zach Sylvester Replied
Employee Post Marked As Answer
Hello, 

Thank you for the question. 
Here is an example in Python. 
import requests
url = "https://mail.domain.com"; # this is the url for the api
def auth(username, password):
    global url 
    authurl = url + "/api/v1/auth/authenticate-user" 
    myobj = {'username': username, 'password':password} 
    data = requests.post(authurl, data = myobj) # this posts the username and password to the api
    print(data.json())
    refreshToken = data.json()['refreshToken'] # this is the refresh token
    accessToken = data.json()['accessToken'] # this is the access token
    accessTokenExpiration = data.json()['accessTokenExpiration'] # this is the access token expiration date
    access_info = {'accessToken': accessToken, 'accessTokenExpiration': accessTokenExpiration, 'refreshToken': refreshToken} # this is the access token, refresh token and expiration info
    return access_info # returns the information

def sendmessage(auth):
    global url
    authurl = url + "/api/v1/mail/message-put"
    myobj = {"to":"\"zsylvester@domain.com\" <zsylvester@domain.com>;","cc":"","bcc":"","ownerEmailAddress":"zsylvester@domain.com","from":"zsylvester@domain.com","replyTo":"zsylvester@domain.com","subject":"test","priority":1,"readReceiptRequested":False,"deliveryReceiptRequested":False,"markForFollowup":False,"messageHTML":"test"}
    header = {'Authorization' : 'Bearer ' + auth}
    data = requests.post(authurl, headers=header ,data = myobj)
    return data.json()


auths = auth('zsylvester@domain.com', 'password')
print(auths)
print(sendmessage(auths['accessToken']))

Here is an example in .NET

using System;
using System.Net.Http;
using System.Text;
using Newtonsoft.Json;

class Program
{
    static HttpClient client = new HttpClient();
    static string url = "https://mail.domain.com";;

    static void Main(string[] args)
    {
        var auths = Auth("zsylvester@domain.com", "password");
        Console.WriteLine(JsonConvert.SerializeObject(auths));

        var messageResponse = SendMessage(auths.access_token);
        Console.WriteLine(JsonConvert.SerializeObject(messageResponse));
    }

    static dynamic Auth(string username, string password)
    {
        string authUrl = url + "/api/v1/auth/authenticate-user";
        var body = new
        {
            username,
            password
        };
        var json = JsonConvert.SerializeObject(body);
        var content = new StringContent(json, Encoding.UTF8, "application/json");
        var response = client.PostAsync(authUrl, content).Result;

        if (!response.IsSuccessStatusCode)
        {
            throw new Exception($"Authentication failed with status code {response.StatusCode}");
        }

        dynamic result = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);

        return new
        {
            access_token = result.accessToken,
            access_token_expiration = result.accessTokenExpiration,
            refresh_token = result.refreshToken
        };
    }

    static dynamic SendMessage(string accessToken)
    {
        string messageUrl = url + "/api/v1/mail/message-put";
        var body = new
        {
            to = "\"zsylvester@domain.com\" <zsylvester@domain.com>;",
            cc = "",
            bcc = "",
            ownerEmailAddress = "zsylvester@domain.com",
            from = "zsylvester@domain.com",
            replyTo = "zsylvester@domain.com",
            subject = "test",
            priority = 1,
            readReceiptRequested = false,
            deliveryReceiptRequested = false,
            markForFollowup = false,
            messageHTML = "test"
        };
        var json = JsonConvert.SerializeObject(body);
        var content = new StringContent(json, Encoding.UTF8, "application/json");
        client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
        var response = client.PostAsync(messageUrl, content).Result;

        if (!response.IsSuccessStatusCode)
        {
            throw new Exception($"Sending message failed with status code {response.StatusCode}");
        }

        return JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
    }
}
Please note that in the C# version, we are using the HttpClient class to make the HTTP requests instead of the requests module in Python. We are also using the Newtonsoft.Json library to serialize and deserialize JSON data.

I hope this helps. 

Kind Regards, 

Zach Sylvester

System/Network Administrator
SmarterTools Inc.
(877) 357-6278
www.smartertools.com
0
ilanmazuz Replied
Thanks a lot Zach, this works as expected.

Can you also include the code on how to add an attachment please? you can add it for the .NET only.

Thanks again,
ilan.
0
ilanmazuz Replied
Zach, i was able to paste image from the clipboard into my HTML editor, and send it as part of the SendMessage() "messageHTM" parameter, which is great.
The only concern i have is if my user will want to attach a file to the email as a separate attachment. I hope you can assist with that.

p.s. i'm not sure if i'll need it, but while we're at it, how can read attachments if there were any in the GetMessage() call?

Thanks a lot,
ilan.
0
ilanmazuz Replied
Hi Zach,

While i am still waiting for your answer about adding Attachments, i also need help on how d i mark the email i am replying to as Read on the server?
Currently neither methods GetMessage nor SendMessage do it. Is there a flag i can set in any/both of them to mark the message as read?

Thanks,
ilan.
0
ilanmazuz Replied
Hello again Zach,
i think i found the additional method i need to call to mark the message as read, since it does not automatically do it when replied to.
the api method i found is PatchMessage, however, even though the response status is ok - the response body is always empty and the email does not get marked as read - so it does not work for some reason and i don't see an error message or something that will tell me what is the issue.

here is my C# code:
private async Task markAsRead()
    {
        //Establish Token for System Admin Communication
        ApiAauthenticateUserResponse authResult = await core.Authenticate_User_Async(Username, Password);
        if (authResult.success == false)
        {
            //Do Nothing - display error message
            lblResult.Text = "failed to get token";
            return;
        }
        else
        {
            //Save Access Token
            accessToken = authResult.accessToken;
            //lblResult.Text = accessToken;
        }

        var url = core.GetOperationURI("mail/message-patch");
        PatchMessage patchMessage = new PatchMessage
        {
            ownerEmailAddress = Username,
            folder="Inbox",
            markRead = true
        };
        patchMessage.uid.Add(Convert.ToInt32(hidLatestMsgId.Value));
        var jsonData = JsonConvert.SerializeObject(patchMessage);
        std.dbg(url, jsonData, accessToken);

        using (var requestMarkAsRead = new HttpRequestMessage(HttpMethod.Post, url))
        {
            requestMarkAsRead.Content = new StringContent(jsonData, Encoding.UTF8, "application/json");
            requestMarkAsRead.Headers.Add("Authorization", "Bearer " + accessToken);

            //std.dbg("Request headers:");
            //foreach (var header in requestMarkAsRead.Headers)
            //{
            //    std.dbg($"{header.Key}: {string.Join(",", header.Value)}");
            //}

            var requestContent = await requestMarkAsRead.Content.ReadAsStringAsync();
            //std.dbg("Request body:");
            //std.dbg(requestContent);

            using (var clientMarkAsRead = new HttpClient())
            {
                var responseMarkAsRead = await clientMarkAsRead.SendAsync(requestMarkAsRead);

                //std.dbg("Response headers:");
                //foreach (var header in responseMarkAsRead.Headers)
                //{
                //    std.dbg($"{header.Key}: {string.Join(",", header.Value)}");
                //}
                std.dbg("Response status code:", responseMarkAsRead.StatusCode, "responseMarkAsRead.IsSuccessStatusCode:", responseMarkAsRead.IsSuccessStatusCode);

                var responseContentMarkAsRead = await responseMarkAsRead.Content.ReadAsStringAsync();
                std.dbg("Response body:");
                std.dbg(responseContentMarkAsRead);

                PatchMessageResponse patchMessageResponse = JsonConvert.DeserializeObject<PatchMessageResponse>(responseContentMarkAsRead);
                // Successful response
                if (responseMarkAsRead.IsSuccessStatusCode)
                {
                    if (!patchMessageResponse.success)
                    {
                        lblSendResults.Text =
                            $"Message Sent but failed to mark As Read. Error Message:{patchMessageResponse.message}.";
                        lblSendResults.CssClass = "error";
                    }
                }
                else // Unsuccessful response
                {
                    lblSendResults.Text = $"Message Sent but failed to mark As Read.";
                    lblSendResults.CssClass = "error";
                }
                //response.EnsureSuccessStatusCode();
            }
        }
    }



The variable responseContentMarkAsRead is always empty, even though the responseMarkAsRead.IsSuccessStatusCode is true.


And to make the code full, here are the 2 classes i am using  in the above code:

public class PatchMessage
{
    public string ownerEmailAddress { get; set; }
    public string folder { get; set; }
    public List<int> uid { get; set; } = new List<int>();
    public bool markDeleted { get; set; }
    public bool markRead { get; set; }
    public bool markReplied { get; set; }
    public bool markForwarded { get; set; }
    public bool markFlagged { get; set; }
    public bool bypassRemoteContent { get; set; }
    public bool markSpam { get; set; }
    public bool markNotSpam { get; set; }
}

public class PatchMessageResponse
{
    public bool success { get; set; }
    public string message { get; set; }
    public Dictionary<string, object> variables { get; set; }
    public string actionGuid { get; set; }
}

Please advise.

Thanks a lot,
ilan.
0
Zach Sylvester Replied
Employee Post
Hey iIan, 

Thanks for getting back to us. Sorry for the late response, we have been super busy with projects and I haven't had a chance to check this thread. In order to send attachments you need to convert the attachment to form data and then send it to the API. 

Regarding your next question marking an email as read you, can use the PatchMessage API call. 

I don't have any examples on hand for these but let me know if you have any questions. 

Kind Regards, 


Zach Sylvester

System/Network Administrator
SmarterTools Inc.
(877) 357-6278
www.smartertools.com
0
ilanmazuz Replied
Thanks Zach.

I was certain i already posted that i found my mistake in the patch email call.
i missed "s" in the name. i used mail/message-patch  instead of mail/messages-patch. So i'm good here and my code above works perfect if anyone else is interested - just correct the api method name.

As for the attachment, i don't understand what you mean by convert the attachment to form data and send it. Can you elaborate?
i did find AddAttachment method in the API, but not sure how to use it - and it seems that you are suggesting something else. So i'll appreciate it if you can explain.

Thanks a lot,
ilan.

Reply to Thread