Mail enabling an SPList programmatically - c#

I am currently building a tool which creates SharePoint sites automatically. Each site must have a mailbox enabled and a specific Email address specified.
I can create the site which by default has a SharePoint list named "mailbox".
My questions is how to I allow the "mailbox" SPList to receive email. There is a property within an SPList called CanReceiveEmail but this is Read-only? So is there another way?
I also need to be able to set the Email address of the SPList programtically, does anyone know the best way to do this?
It can be done manually but this is not an option.

A simple list (as far as I know but I may be wrong) does not have the ability to receive emails. You can create a custom list that does.
You can create a document library, which by default has this ability.
How these properties are set, you can see when you examine the code (using Lutz Roeder's Reflector, http://www.red-gate.com/products/reflector/) of /_layouts/EmailSettings.aspx which can be found in "Microsoft.SharePoint.ApplicationPages.dll" found on your server in path something like
\\server\c$\Inetpub\wwwroot\wss\VirtualDirectories\80\_app_bin.
So you will have to set multiple properties of the "rootfolder" of the document library.
The code is as follows :
Protected Sub SubmitButton_Click(ByVal sender As Object, ByVal args As EventArgs)
If Me.EnabledTrue.Checked Then
If ((Me.TxtAlias.Text Is Nothing) OrElse (Me.TxtAlias.Text.Length = 0)) Then
Throw New SPException(SPResource.GetString("MissingEmailAlias", New Object(0 - 1) {}))
End If
'This will be the receiving e-mail address
Me.m_List.EmailAlias = Me.TxtAlias.Text
'do we need to check users permissions on items
Me.m_RootFolder.Properties.Item("vti_emailusesecurity") = IIf(Me.UseSecurityTrue.Checked, 1, 0)
If Me.ShowSaveAttachments Then
'options how to save attachments, root folder, grouped, whatever
Me.m_RootFolder.Properties.Item("vti_emailsaveattachments") = IIf(Me.SaveAttachmentsTrue.Checked, 1, 0)
End If
If Me.ShowSaveOriginalAndMeetings Then
Me.m_RootFolder.Properties.Item("vti_emailsavemeetings") = IIf(Me.MeetingsTrue.Checked, 1, 0)
Me.m_RootFolder.Properties.Item("vti_emailsaveoriginal") = IIf(Me.SaveOriginalTrue.Checked, 1, 0)
End If
If Me.ShowAttachmentFolders Then
Me.m_RootFolder.Properties.Item("vti_emailoverwrite") = IIf(Me.OverwriteTrue.Checked, 1, 0)
If Me.AttachmentFoldersSender.Checked Then
Me.m_RootFolder.Properties.Item("vti_emailattachmentfolders") = "sender"
ElseIf Me.AttachmentFoldersSubject.Checked Then
Me.m_RootFolder.Properties.Item("vti_emailattachmentfolders") = "subject"
Else
Me.m_RootFolder.Properties.Item("vti_emailattachmentfolders") = "root"
End If
End If
If Me.ShowAutoApprove Then
'I think this is something when content approval is enabled.
Me.m_RootFolder.Properties.Item("vti_emailautoapprove") = IIf(Me.AutoApproveTrue.Checked, 1, 0)
End If
ElseIf Me.EnabledFalse.Checked Then
Me.m_List.EmailAlias = Nothing
End If
Me.m_RootFolder.Update
Me.m_List.ResetContentTypes
Me.m_List.Update
SPUtility.Redirect((IIf((Me.m_List.BaseType = SPBaseType.Survey), "survedit", "listedit") & ".aspx?List=" & Me.m_List.ID.ToString), SPRedirectFlags.RelativeToLocalizedLayoutsPage, Me.Context)
End Sub
EDIT: added comments to my code

Related

Can I somehow convert attachments I get from Outlook Add In to pdf?

I am currently making an Outlook Add In and I successfully got the attachments from an email.
Here is the attachment:
And here is the method:
public static List<AttachmentResponse> GetAttachments(
AttachmentSampleServiceRequest request)
{
// Create an ExchangeService object, set the credentials and the EWS URL.
var service = new ExchangeService
{
Credentials = new OAuthCredentials(request.AttachmentToken),
Url = new Uri(request.EwsUrl)
};
var result = new List<AttachmentResponse>();
var getAttachmentsResponse =
service.GetAttachments(request.Attachments.Select(attachment => attachment.id).ToArray(),
null,
new PropertySet(BasePropertySet.FirstClassProperties,
ItemSchema.MimeContent));
var getAttachmentResponsesFiltered = getAttachmentsResponse.Where(file =>
file.Result == ServiceResult.Success && file.Attachment.ContentType == "application/pdf");
{
result.AddRange(from attachmentResponse in getAttachmentResponsesFiltered
let fileAttachment = attachmentResponse.Attachment as FileAttachment
let base64String =
Convert.ToBase64String(fileAttachment?.Content, 0, (int) fileAttachment?.Content.Length)
select new AttachmentResponse
{
Id = attachmentResponse.Attachment.Id, Name = attachmentResponse.Attachment.Name,
Type = attachmentResponse.Attachment.ContentType, FileBase64 = base64String
});
}
return result;
}
The Open XML SDK which you could use on the server-side doesn't provide anything for generating PDF files. You may try to use something like iText or iTextSharp or any other third-party components designed for the server-side execution.
In case of COM add-ins there is no need to use EWS at all. Use the Attachments property of Outlook items to deal with attached files and items. The MailItem.Attachments property returns an Attachments object that represents all the attachments for the specified item. You can access attachments in the collection by using the either the index number of the object, or a value used to match the default property of an object in the collection. For example, here is a sample VBA code which illustrates how you could use the Outlook object model from your add-in:
Sub SaveAttachment()
Dim myInspector As Outlook.Inspector
Dim myItem As Outlook.MailItem
Dim myAttachments As Outlook.Attachments
Set myInspector = Application.ActiveInspector
If Not TypeName(myInspector) = "Nothing" Then
If TypeName(myInspector.CurrentItem) = "MailItem" Then
Set myItem = myInspector.CurrentItem
Set myAttachments = myItem.Attachments
'Prompt the user for confirmation
Dim strPrompt As String
strPrompt = "Are you sure you want to save the first attachment in the current item to the Documents folder? If a file with the same name already exists in the destination folder, it will be overwritten with this copy of the file."
If MsgBox(strPrompt, vbYesNo + vbQuestion) = vbYes Then
myAttachments.Item(1).SaveAsFile Environ("HOMEPATH") & "\My Documents\" & myAttachments.Item(1).DisplayName
End If
Else
MsgBox "The item is of the wrong type."
End If
End If
End Sub

Converting VBS code to C#

I just have the below code that was provides as hMailServer's DCOM API at http://www.hmailserver.com/documentation/latest/?page=com_example_account_create The below script works fine. It has no reference nothing. Just after installing hMailServer, running the below code can create an account. Now, I need the same thing in C#. They didn't provide me with any library for C# I googled for it but no relevant results all I have is the below code but in according to hMailServer API they said you can convert the below script to any language that you want. But how? I can't even understand how to start to write even the first line. Anybody please help me.
Dim obApp
Set obApp = CreateObject("hMailServer.Application")
' Authenticate. Without doing this, we won't have permission
' to change any server settings or add any objects to the
' installation.
Call obApp.Authenticate("Administrator", "your-main-hmailserver-password")
' Locate the domain we want to add the account to
Dim obDomain
Set obDomain = obApp.Domains.ItemByName("example.com")
Dim obAccount
Set obAccount = obDomain.Accounts.Add
' Set the account properties
obAccount.Address = "account#example.com"
obAccount.Password = "secret"
obAccount.Active = True
obAccount.MaxSize = 100 ' Allow max 100 megabytes
obAccount.Save
Add the COM object (hMailServer) to your C# project as a reference and translate the rest of the code to C#.
It will look something like this:
var app = new hMailServer.Application();
// Authenticate. Without doing this, we won't have permission
// to change any server settings or add any objects to the
// installation.
app.Authenticate("Administrator", "your-main-hmailserver-password");
// Locate the domain we want to add the account to
var domain = app.Domains["example.com"];
var account = domain.Accounts.Add();
// Set the account properties
account.Address = "account#example.com";
account.Password = "secret";
account.Active = true;
account.MaxSize = 100; // Allow max 100 megabytes
account.Save();
I hope this is still relevant and can help someone. Here I simply used the get item by name property to pull the domain name configured in the hMailServer.
protected void Page_Load(object sender, EventArgs e)
{
var app = new hMailServer.Application();
// Authenticate. Without doing this, we won't have permission
// to change any server settings or add any objects to the
// installation.
app.Authenticate("Administrator", "your.admin.password.here");
// Locate the domain we want to add the account to
var domain = app.Domains.get_ItemByName("your.configured.domain.name.here");
var account = domain.Accounts.Add();
// Set the account properties
account.Address = "account.name.here";
account.Password = "pass.word.here";
account.Active = true;
account.MaxSize = 100; // Allow max 100 megabytes
account.Save();
}

How can I create a custom sortable field in Outlook populated by a formula?

Having successfully created a custom field in Outlook via a formula and parsing the Subject field; I have now hit a new snag. The custom field is not sortable. It appears as of current that the only way to achieve this is to create a new user property which would then be sortable and could be leveraged when defining the field.
The option also exists to push everything into either a VBA script or C# app using the interop. Either way would work for me however I would prefer to go the VBA route and keep it self contained.
The emails exist in a folder and can be ran after the fact; the solution does not need to remain constantly active.
If anyone could point me to code which can easily achieve this that would be great. If I am missing an option to make the custom field sortable then please provide the alternative as that is the end goal.
EDIT:
This is what I currently have...
Sub SortCustomField()
Dim olApp As Outlook.Application
Dim objLotusInbox As Outlook.MAPIFolder
Dim objLotusInboxItems As Outlook.Items
Dim objNameSpace As Outlook.NameSpace
Dim objProperty As Outlook.UserDefinedProperty
Set olApp = CreateObject("Outlook.Application")
Set objNameSpace = olApp.GetNamespace("MAPI")
Set objLotusInbox = objNameSpace.GetDefaultFolder(olFolderInbox).Folders("Lotus Notes Inbox")
Set objLotusInboxItems = objLotusInbox.Items
objLotusInboxItems.Sort "[Notes2Outlook Created]", False
Set objLotusInboxItems = Nothing
Set objLotusInbox = Nothing
Set objNameSpace = Nothing
Set olApp = Nothing
End Sub
Erroring out at the sort; pretty certain it is due to the fact that the stated field is a user defined field as it works on other fields such as From.
UPDATE:
Made some ground, however when going back to Outlook it does not appear to populate the field defined during the run.
Dim olApp As Outlook.Application
Dim objLotusInbox As Outlook.MAPIFolder
Dim objLotusInboxItems As Outlook.Items
Dim objNameSpace As Outlook.NameSpace
Dim objMailProperty As Outlook.UserProperty
Dim objMailItem As Outlook.MailItem
Dim objParsedDate As Date
Dim sample As Object
Set olApp = CreateObject("Outlook.Application")
Set objNameSpace = olApp.GetNamespace("MAPI")
Set objLotusInbox = objNameSpace.GetDefaultFolder(olFolderInbox).Folders("Lotus Notes Inbox")
Set objLotusInboxItems = objLotusInbox.Items
For Each objMailItem In objLotusInboxItems
Set objMailProperty = objMailItem.UserProperties.Add("MyUserProp", olDateTime)
objParsedDate = CDate(Mid(objMailItem.Subject, (InStr(objMailItem.Subject, "[") + 1), (InStr(objMailItem.Subject, "]") - InStr(objMailItem.Subject, "[")) - 1))
objMailProperty.Value = objParsedDate
Next
Set objLotusInboxItems = Nothing
Set objLotusInbox = Nothing
Set objNameSpace = Nothing
Set olApp = Nothing
I was having the same problem using c# and Add-in-express VSTO addin.
I solved it by saving the MailItem object after I has made the property change.
So for your code I would do the following:objMailItem.Save at the pertinent point. Namely at the end of each iteration of the For loop.
NB: In my c# code I use Marshal.ReleaseComObject for the USerProperty assigned object.
Since you are populating it in the VBA already you should be able to change the User-Property to a text field which can be sorted.
The method I use is running a script based on a rule but in your case you can call it as a sub in the for-each loop.
Sub SomeAction(Item As Outlook.MailItem)
Dim myProperty As Outlook.UserProperty
Set myProperty = Item.UserProperties.Add("MyUserProp", olText, True)
myProperty.Value = Mid(objMailItem.Subject, (InStr(objMailItem.Subject, "[") + 1), (InStr(objMailItem.Subject, "]") - InStr(objMailItem.Subject, "[")) - 1))
Item.Save
Set myProperty = Nothing
End Sub
Only thing left to do is add a user defined column in your view which is a Text based user defined field.
note, since you are using a Date/Time item, this method should work just as well when you define the UserProperty as olDateTime
I've combined the answers from above to add a user defined column which is populated by running a rule selecting the script. I can then sort my inbox by the senders domain. My thanks to the previous contributors.
Public Sub SortByDomain(oMsg As Outlook.MailItem)
On Error Resume Next
Dim sDomain As String 'The Sender's domain
Dim oNS As Outlook.NameSpace 'My namespace
Dim oInbox As Outlook.MAPIFolder 'My Inbox
Dim oTarget As Outlook.MAPIFolder 'The domain folder
Dim myProperty As Outlook.UserProperty
'If it's not your domain, decipher the domain.
If InStr(oMsg.SenderEmailAddress, "mydomain.com") < 1 Then
sDomain = Mid(oMsg.SenderEmailAddress, InStr(oMsg.SenderEmailAddress, "#") + 1)
Else
sDomain = "mydomain.com"
End If
Set myProperty = oMsg.UserProperties.Add("SenderDomain", olText, True)
myProperty.Value = sDomain
oMsg.Save
'Cleanup.
Set oTarget = Nothing
Set oInbox = Nothing
Set oNS = Nothing
Set myProperty = Nothing
End Sub

List of computers in Active Directory that are online

I'm using this snippet of code to output a list of all the computers on my network (the language is jscript.net, but it's just a small manipulation of C#).
var parentEntry = new DirectoryEntry();
parentEntry.Path = "WinNT:";
for(var childEntry in parentEntry.Children) {
if(childEntry.SchemaClassName == "Domain") {
var parentDomain = new TreeNode(childEntry.Name);
this.treeView1.Nodes.Add(parentDomain);
var subChildEntry : DirectoryEntry;
var subParentEntry = new DirectoryEntry();
subParentEntry.Path = "WinNT://" + childEntry.Name;
for(subChildEntry in subParentEntry.Children) {
var newNode1 = new TreeNode(subChildEntry.Name);
if(subChildEntry.SchemaClassName == "Computer") {
parentDomain.Nodes.Add(newNode1);
}
}
}
}
I have 2 issues with this:
1) It is extremely slow. There's about 100 computers showing, and it takes about 1 minute to load.
2) I want to get only a list of computers that are currently online.
This can be done because I've seen other programs doing it and they are much faster, also they're able to show only the ones online.
Am I missing something?
I know it's a bit old, but for others...this snippet will return a 760 computer names from a domain using AD within 2-3 seconds....a significant improvement....enjoy!
Friend Shared Function DomainComputers() As Generic.List(Of String)
' Add a Reference to System.DirectoryServices
Dim Result As New Generic.List(Of String)
Dim ComputerName As String = Nothing
Dim SRC As SearchResultCollection = Nothing
Dim Searcher As DirectorySearcher = Nothing
Try
Searcher = New DirectorySearcher("(objectCategory=computer)", {"Name"})
Searcher.Sort = New SortOption("Name", SortDirection.Ascending)
Searcher.Tombstone = False
SRC = Searcher.FindAll
For Each Item As SearchResult In SRC
ComputerName = Item.Properties("Name")(0)
Result.Add(ComputerName)
Next
Catch ex As Exception
End Try
Return Result
End Function
I would look at Linq To Active Directory found on CodePlex
You'd also have to define "my network". Your subnet? Your Organizational Unit? Your domain? Your forest?
Also consider where your LDAP server is that you are querying. Is it close or is it on the other end of a remote link?
Also what do you consider "online"? Do you expect to be able to ping it? Do you expect to be able to connect to it and perform an operation?
There are many things to consider here. Also if you have other infrastructure components such as an SCCM / SMS server they can often be queried much faster since all of the discovery data has flowed up into the data warehouse.

Are there any Outlook Contacts Controls in ASP.NET?

How can I access Microsoft Outlook contacts using ASP.NET? Are there any controls that can do this?
If by control you mean api, there already is one - Exchange Web Services (EWS). Assuming you are dealing with exchange, and have EWS set up. The web services usually sit at:
https://[yourmaildomain.com]/EWS/Exchange.asmx
Here is some quick code - not production tested (also in vb.net)
Dim esb As New ExchangeServiceBinding()
esb.Credentials = New NetworkCredential("someusername", "somepassword")
esb.Url = "https://[yourmaildomain.com]/EWS/Exchange.asmx"
Dim addressType As New EmailAddressType()
With addressType
.EmailAddress = "email#domain.com"
.MailboxType = MailboxTypeType.Mailbox
.MailboxTypeSpecified = True
End With
' properties
Dim itemProperties As New ItemResponseShapeType()
itemProperties.BaseShape = DefaultShapeNamesType.AllProperties
' Identify which folders to search to find items.
Dim folderIDs(0) As DistinguishedFolderIdType
folderIDs(0) = New DistinguishedFolderIdType()
folderIDs(0).Id = DistinguishedFolderIdNameType.contacts
folderIDs(0).Mailbox = addressType
Dim findItemRequest As New FindItemType()
findItemRequest.Traversal = ItemQueryTraversalType.Shallow
findItemRequest.ItemShape = itemProperties
findItemRequest.ParentFolderIds = folderIDs
' send request
Dim findItemResponse As FindItemResponseType = esb.FindItem(findItemRequest)
Dim rmta As ResponseMessageType() = findItemResponse.ResponseMessages.Items
For Each rmt As ResponseMessageType In rmta
If rmt.ResponseClass = ResponseClassType.Success Then
Dim firmt As FindItemResponseMessageType = CType(rmt, FindItemResponseMessageType)
If firmt IsNot Nothing Then
Dim root As FindItemParentType = firmt.RootFolder
Dim obj As Object = root.Item
If TypeOf obj Is ArrayOfRealItemsType Then
Dim items As ArrayOfRealItemsType = DirectCast(obj, ArrayOfRealItemsType)
If items.Items IsNot Nothing Then
For Each it As ItemType In items.Items
If TypeOf it Is ContactItemType Then
Dim cit As ContactItemType = DirectCast(it, ContactItemType)
Response.Write("<p>")
Response.Write(cit.Subject)
Response.Write("<p>")
End If
Next
End If
End If
End If
End If
Next
FROM Microsoft Support:
How to use the Microsoft Outlook Object Library to retrieve a contact by using Visual C#
MSDN:
Outlook Object Model Overview
How to: Access Outlook Contacts (Some more nice how to's at the end)
You would need to create an ActiveX Application that the client would install to allow you access to this. Unless it's an internal development project, don't expect people to install something that gives you access to their email program.

Categories