Welcome to AspAdvice Sign in | Join | Help

.Net Discoveries

An attempt to pass along some answers I have discovered in my .Net coding.
VB.Net and GroupWise Soap Pt. 3 - Creating a Message

Prologue

In my last post, I talked about accessing GroupWise via the SOAP services that they provide. Specifically, we looked at getting a folder list. In this post I want to expand upon the application that we started and add some more functionality.

Problem

Our problem, continued from the last post, was to figure out how to login and create a draft message in the user's Work in Progress folder that is a template of something the company uses currently in hard copy. In this article, I'm going to look specifically at how to create a message as a draft, and place it in a specific folder. Technically this will meet the requirements I set forth in the first post, but (and there's always a but isn't there?), I want to create an HTML draft message. The HTML template will not be covered in this post, and for that matter I haven't gotten it to work yet, so if anyone has any suggestions, please let me know.

Solution

We will be building on the application that we started last time. If you haven't created the login procedures from Part 1 and the folder listing subroutines from Part 2, I suggest you do it now, we will need to login and we need to be able to get a folder's ID.

We actually have very little in the way of preparation. We simply need to add some controls so that we can create a message. We won't create any new helper functions yet. Let's add two more buttons, name one btnSendMessage, set the text to 'Send Message' and name the other btnCreateMessage and set it's text to 'Create Message'. For both buttons, set their enabled property to false. Next create two text boxes, txtSubject and txtTo and create one multiline text box and name it txtMessage (you may want to add labels to go with them).

One last thing to do is to add our new buttons to the ToggleButtons() function. Just below btnListFolders.Enabled = True, add the following:

btnSendMessage.Enabled = True
btnCreateMessage.Enabled = True

and add the opposite just below btnListFolders.Enabled = False, add the following:

btnSendMessage.Enabled = False
btnCreateMessage.Enabled = False

Basically, this just ensures that we can't attempt to send or create a message on the server without being logged in first.

As you can guess, there are two methods in GroupWise SOAP that we can use to create messages. I am choosing to show both, because they create things a little bit different. Let's start with SENDING a message first, then we'll take a short look at creating one since it is very similar. Start by creating a new subroutine for sending a message:

Public Sub SendMessage()

End Sub

Hook up your btnSendMessage button's click event to this subroutine. Now we want to get started with our message. To begin with, we'll need some specific objects such as a sendItemRequest and a sendItemResponse. We'll also need to create a Mail item to send as a parameter in our request. Define them as follows in your subroutine:

Dim gwMail As New GWWS.Mail
Dim gwSendReq As New GWWS.sendItemRequest
Dim gwSendResp As New GWWS.sendItemResponse

This creates and instantiates all three of our necessary pieces. The sendItemRequest expects us to pass in an item (an appointment, or a mail item for example) and then it will process the item and return a response.

Now we're ready to begin loading our mail item with our settings. Let's start with the easy stuff first.:

gwMail.subject = txtSubject.Text

Ok, that's the end of the EASY stuff, the rest of it gets a little more complicated. It can't be as easy as just packing up the information and sending it, NOOO, we need to convert things to arrays and add the arrays. Some are easier than others. The first one we'll tackle is one of the more difficult ones to figure out but once you figure it out, it isn't really all that bad. Lets start by creating a new helper function, define it as follows: 

Private Function ConvertStringToMessagePart(ByVal sStringToConvert _
   As String) As GWWS.MessagePart

End Function

We cannot just assign the text of our message box to the message, we actually need to encode it as an array of bytes, add it to a MessagePart object, and then add the MessagePart object to the MessageParts array. This function will be used to bring in our message text, convert it into a byte array, add it to a MessagePart and then return the finished MessagePart. First we need to create an encoding object and then create the MessagePart to return. Add the following to your subroutine:

Dim encoding As System.Text.Encoding = System.Text.Encoding.UTF8
Dim gwMessagePart As New GWWS.MessagePart

First we create an encoding object. Then we assign it UTF8 encoding. This will encode our message into the ASCII encoding it's expected to be in. Second we create a new MessagePart object. Now we need to load it up with the byte array containing our message text and return it. Add the following:

gwMessagePart.Value = encoding.GetBytes(sStringToConvert)
gwMessagePart.length = 0
Return gwMessagePart

We use our encoding object to return an array of bytes by using the GetBytes function. Basically, we return an array of ASCII values, one element for each character of the string we're converting. This array is then assigned to the MessagePart we created. Now it might seem a little strange to set the length of the MessagePart to 0, and you'd be right, but apparently there is a bug in the server code, so if you set it manually, your message get's cut short. I believe the documentation online instructs you to set it manually, but it doesn't work, you'll get your message, but about 1/3 of your message will be missing. So we set it to 0 and the server will do the calculation itself (easier anyhow...). Finally we return the MessagePart we just created.

Now we're ready to use helper function in our main function. Add the following to your SendMessage subroutine code:

Dim gwMessageParts(0) As GWWS.MessagePart
gwMessageParts(0) = ConvertStringToMessagePart(txtMessage.Text)
gwMail.message = gwMessageParts

We start by creating an array of MessageParts with one element (Honestly, I'm not sure the benefit of having multiple message parts, anyone out there know?). Next we assign the encoded message text from the form, returned as a MessagePart to the first element of the array. Finally, we assign our MessageParts array to the message property of our mail item. Next we'll want to address our message so it can go into somebody's folder. We need to create 2 objects for addressing, one for the distribution list and one an array for the recipients. Add the following to your code:

Dim gwDistribution As New GWWS.Distribution
Dim gwRecipients(0) As GWWS.Recipient

In this example, we've only allowed for one recipient, thus we created a recipients array with a single element. Now we want to create a single recipient, load it up and add all the pieces together. Add the following lines to your code:

Dim gwRecipient As New GWWS.Recipient
gwRecipient.email = txtTo.Text
gwRecipient.distType = GWWS.DistributionType.TO
gwRecipients(0) = gwRecipient
gwDistribution.recipients = gwRecipients
gwMail.distribution = gwDistribution

First we create a new recipient object, then we load its properties with the email address and the distribution type. Next, we add our recipient to the recipients array (ok, this array makes sense to me, you may easily have more than one recipient...). Finally we add the recipient array to the distribution and assign our distribution to the mail item. (Phew..)

Technically we are now ready to send the item, we just need to add some code to do the actual sending but, our item is ready for delivery as it is. So let's add that code and then go back and add in some options. Add the following code:

gwSendReq.item = gwMail
gwSendResp = wsGWBinding.sendItemRequest(gwSendReq)
If gwSendResp.status.code = 0 Then
  ReportStuff("Send Mail Status: Success.")
Else
  ReportStuff("Send Mail Status: Failure, Code: " & gwSendResp.status.code) End If

So we assign our mail item to the item property of the sendItemRquest object we created, and then use the sendItemReqeust to send our item. We capture the returned sendItemResponse and parse it to see if we succeeded in sending our message and report. Run your program and test it. Send a message twice, once to yourself and once to a co-worker. It should successfully send a message to both yourself and the co-worker. Where do the messages end up? Both messages are successfully sent to the recipient's inbox.

Ok, now we want to add some options. We wanted to do two things that we haven't done yet. We wanted to create the item as a draft, and we wanted to create it in the 'Work In Progress' folder. So let's start by making it draft, perhaps that will automatically put it in the Work In Progress folder? (no such luck, but you can think that for a moment if you want to...). Add the following code to specify that we have a draft message and put it after our recipient section but before our sending section:

Dim gwItemSource As GWWS.ItemSource
gwItemSource = GWWS.ItemSource.draft
gwMail.source = gwItemSource
gwMail.sourceSpecified = True

We create an ItemSource object and then assign it to be a draft message. Next we add it to the source property of our mail item and then let the item know that ItemSource is specified.

Go ahead and run your application again try to send it the same two ways (once with your email address as the recipient, and then try it with a co-worker's as the recipient). What happens? Where does the message end up? In both instances, the message will show up as a draft in YOUR mailbox. There are two things to note here. 1) Even though you specified a co-worker as the recipient, the message was sent to YOUR inbox, and 2) labeling the item as draft did NOT put it into the 'Work In Progress' folder automatically. Ok so why does the co-worker's email send correctly before but end up in your inbox now? Well, that's because it is a draft, you can't SEND a draft to someone else, you have to complete it (thus your co-worker's email in your inbox). So it shows up in your inbox. So why the inbox? Well, that's related to #2 and we'll talk about that a little more in a second. First, let's try to specify a folder to create the new item in. Add the directly after the ItemSource section:

Dim gwContainerRef(0) As GWWS.ContainerRef
gwContainerRef(0) = New GWWS.ContainerRef()
gwContainerRef(0).Value = GetFolderIDByName("Work In Progress")
gwMail.container = gwContainerRef

By now you should be getting used to the array concept. We create a container reference object, as a single element array of ContainerRef. Then we initialize the element with a concrete object. Then we access the value property and assign in the ID of the folder we want to create the message in (Work in Progress) using the helper function we created in the last exercise (Part 2). Finally, we assign our containerRef array to the mail item's container property. Run it again and just send one to yourself this time. What happens? The message still ends up in the inbox. Why? The simple answer is this, you SENT it. If you send an email, you cannot specify where the recipient will receive it. Even though you sent it to yourself, you SENT it and because it was SENT to you it bypasses the container information and DELIVERS it to the inbox (as opposed to creating it).

So how do we create a message in a folder? Well there is another method for that. I alluded to it before. We CREATE an item rather than sending, and then we can specify where it goes. Realistically, all the code is pretty much the same with the exception that we need to change all our sentItem stuff (req, response, etc.) to CREATE (i.e. copy and paste, then change). Rather than try to specify all the lines that need changed, I'll just post the final CreateMessage subroutine code. It looks like this:

Public Sub CreateMessage()
   Dim gwMail As New GWWS.Mail
   Dim gwDistribution As New GWWS.Distribution
   Dim gwMessageParts(0) As GWWS.MessagePart
   Dim gwCreateReq As New GWWS.createItemRequest
   Dim gwCreateResp As New GWWS.createItemResponse

   gwMail.subject = txtSubject.Text
   gwMessageParts(0) = ConvertStringToMessagePart(txtMessage.Text)
   gwMail.message = gwMessageParts

   Dim gwRecipients(0) As GWWS.Recipient
   Dim gwRecipient As New GWWS.Recipient
   gwRecipient.email = txtTo.Text
   gwRecipient.distType = GWWS.DistributionType.TO
   gwRecipients(0) = gwRecipient
   gwDistribution.recipients = gwRecipients
   gwMail.distribution = gwDistribution

   Dim gwItemSource As GWWS.ItemSource
   gwItemSource = GWWS.ItemSource.draft
   gwMail.source = gwItemSource
   gwMail.sourceSpecified = True

   Dim gwContainerRef(0) As GWWS.ContainerRef
   gwContainerRef(0) = New GWWS.ContainerRef()
   gwContainerRef(0).Value = GetFolderIDByName("Work In Progress")
   gwMail.container = gwContainerRef

   gwCreateReq.item = gwMail
   gwCreateResp = wsGWBinding.createItemRequest(gwCreateReq)
   If gwCreateResp.status.code = 0 Then
      ReportStuff("Create Mail Status: Success.")
   Else
      ReportStuff("Create Mail Status: Failure, Code: " & _
         gwCreateResp.status.code)
   End If
End Sub

Assign the click event of your btnCreateMessage to this subroutine. Run your program and rather than send a message, create a message. Create one to yourself and one to your co-worker. What happens? Where does the message end up? Yes, both are created as draft message and both end up in YOUR 'Work In Progress' folder (remember that draft thing). Even if you take the draft and folder section out of the subroutine, we cannot CREATE a message in somebody else's account. So if you comment out the Draft and Folder portion above and send to a co-worker, guess what? A new message appears in YOUR inbox.

As an FYI, creating a message actually bypasses the Rules that you have setup (under Tools->Rules). This is because the item is CREATED in the folder, rather than sent. There isn't a rule event to act on CREATED items, just RECEIVED Items.

Epilogue

We've come a long way towards our goal, we've created a message, created it as a draft and finally, we've got it to go into the folder that we specify. Like I said earlier, technically we've satisfied the requirements set forth in Part 1, but I'd like to make the draft mail item an HTML message. I'd like to say that I'll show you next time how to create an HTML draft message, but unfortunately, it hasn't been working for me. When I figure it out, there'll be a Part 4, I just don't know when that'll be.

Sponsor
Posted: Tuesday, September 04, 2007 5:53 PM by Yougotiger

Comments

.Net Discoveries said:

Prologue In my last few posts, I talked about accessing GroupWise via the SOAP services that they provide.

# October 4, 2007 7:55 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Enter the code you see below

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS