Mohammed 的个人资料Dynamics AX日志留言簿网络 工具 帮助

日志


1月18日

Import Emails from Outlook 2007 into Dynamics AX 2009

 

One of the really good features of Dynamics AX, is the ability to send Emails directly from the application... hence we can email invoices as pdf attachments directly from Dynamics AX..

However, there isnt a automated method of importing Emails from outlook into Dynamics.. one can manually attach emails to a record using the Document Handling functionality.... this functionality is best used in CRM where one can drag a email from Dynamics and drop it in ax (CRM > Encyclopaedia or CRM > Documents).. however the drag and drop (even though its cool) its still manual..

This project basically gives you the ability to import email from outlook in to ax... the code can either be executed on a periodic basis or can be a part of the client start up..

The code here is designed to read emails from the users Inbox and then on a basis of certain parameters, it find out which record in ax the email should be attached to..

The parameters work in 2 ways..

1. Subject Line Prefixes

If you ever worked with a Email integrated ‘Bug tracking System’ then you would know what I am talking about..

Subject line code work the following way..

For example say we create a code for sales.. sales# .. this basically means that if a subject has the word ‘sales#’ then the characters following the code (sales#) signify the sales Id the email needs to be related to.

In this project I added two subject line prefix codes.. one for Sales and the other for Customer... so for example if the subject line has the word ‘cust#’ then the characters following the code specify the customer account number.

2. From Email Address

I added a parameter, so that apart from the above option, one can also search for the record (custTanble or ContactPerson) using the email address of the sender.

Note: you might want to revisit indexes on custTable and Contact person if you like to take this path.

Ohh... in addition to that, if a match is found.. i.e. we find a email that should be attached to a ax record, then after importing the mail into ax, the routine transfer the mail to a folder (specified in the parameters table), hence the mail wont be searched by the routine again.

I dont think I need to say any more.. the code is pretty much self explanatory and were ever I deemed necessary I added comments to explain what I was up to ..

Note: I would like to point out that this is totally untested code, and there are no warranties or guarantees that I or my company provide on the usage of this code... this code was written to show one of the many ways in which ax integrates with Office Systems and was not meant to be used in a production environment.

clip_image001

class mrOutlookImporter

{

mrOutlookImportParameters outLookPram;

docuRef docuRef;

Microsoft.Office.Interop.Outlook.MailItemClass mailItemClass;

}

void getMails()

{

Microsoft.Office.Interop.Outlook._Application outAppl;

Microsoft.Office.Interop.Outlook.MAPIFolder mapiFolder;

Microsoft.Office.Interop.Outlook.NameSpaceClass Nspace;

Microsoft.Office.Interop.Outlook.FoldersClass foldersClass;

Microsoft.Office.Interop.Outlook.ItemsClass itemClass;

Microsoft.Office.Interop.Outlook.MAPIFolder destinationFolder;

//str dd;

str folderName;

str mailSubject;

str fromEmail;

str entryId;

str storeId;

int numOfEmails;

int numOfFolders;

boolean copyToDestination = false;

;

select firstonly outLookPram;

new InteropPermission(InteropKind::ClrInterop).assert();

outAppl = new Microsoft.Office.Interop.Outlook.ApplicationClass();

nSpace = outAppl.GetNamespace('Mapi');

mapiFolder = nSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders::olFolderInbox);

foldersClass = mapiFolder.get_Folders();

numOfFolders = foldersClass.get_Count();

destinationFolder = foldersClass.GetFirst();

while(numOfFolders > 0)

{

folderName = destinationFolder.get_Name();

if(folderName == outLookPram.outlookFolder)

{

copyToDestination = true;

break;

}

destinationFolder = foldersClass.GetNext();

numOfFolders--;

}

if(!copyToDestination)

{

try

{

foldersClass.Add(outLookPram.outlookFolder,Microsoft.Office.Interop.Outlook.OlDefaultFolders::olFolderInbox);

copyToDestination = true;

}

catch(Exception::CLRError)

{

error('cannot create folder');

}

}

itemClass = mapifolder.get_Items();

mailItemClass = itemClass.GetFirst();

numOfEmails = itemClass.get_Count();

while( numOfEmails > 0)

{

try

{

numOfEmails--;

mailSubject = mailItemClass.get_Subject();

fromEmail = mailItemClass.get_SenderEmailAddress();

entryId = mailItemClass.get_EntryID();

storeId = mapifolder.get_StoreID();

if(copyToDestination && this.validateEmail(mailSubject))

{

if(this.importEmail(entryId,storeId))

mailItemClass.Move(destinationFolder);

}

else if(copyToDestination && outLookPram.checkUsingEmailAddress == NoYes::Yes)

{

if(this.findAndSetDocuref('email',fromEmail,mailSubject))

{

if(this.importEmail(entryId,storeId))

mailItemClass.Move(destinationFolder);

}

}

// one might consider moving a mail to a different folder even if a match isnt found.

mailItemClass = itemClass.GetNext(); //

}

catch(Exception::CLRError)

{

error('cannot read email');

continue;

}

}

CodeAccessPermission::revertAssert();

}

boolean validateEmail(str _subject)

{

int firstPos;

int secondPos;

;

//scan sales

if(strScan(_subject,outLookPram.salesPrefix,1,strlen(_subject)))

{

firstPos = strScan(_subject,outLookPram.salesPrefix,1,strlen(_subject));

secondPos = strScan(_subject,'',firstPos,strlen(_subject));

return this.findAndSetDocuref('sales',substr(_subject,firstPos,(secondPos-FirstPos)),_subject);

}

else if(strScan(_subject,outLookPram.custPrefix,1,strlen(_subject)))

{

firstPos = strScan(_subject,outLookPram.custPrefix,1,strlen(_subject));

secondPos = strScan(_subject,'',firstPos,strlen(_subject));

return this.findAndSetDocuref('Cust',substr(_subject,firstPos,(secondPos-FirstPos)),_subject);

}

return false;

}

boolean findAndSetDocuref(str _type,str _num,str _subject)

{

SalesTable salesTable;

CustTable custTable;

ContactPerson contactPerson;

salesId salesId;

custAccount custAccount;

email email;

;

this.initDocuref(_subject);

Switch(_type)

{

Case 'sales' :

{

salesId = _num;

select firstonly recid,ContactPersonId from salesTable where salesTable.SalesId == salesId;

if(salesTable.recid)

{

docuref.RefRecId = salesTable.RecId;

docuRef.RefTableId = tablenum(SalesTable);

docuref.ContactPersonId = salesTable.ContactPersonId;

return true;

}

break;

}

Case 'cust' :

{

custAccount = _num;

select firstonly recid,ContactPersonId from custtable where custTable.AccountNum == custAccount;

if(custTable.RecId)

{

docuref.RefRecId = custTable.RecId;

docuRef.RefTableId = tablenum(custTable);

docuref.ContactPersonId = custTable.ContactPersonId;

return true;

}

break;

}

Case 'email' :

{

email = _num;

select firstonly ContactPersonId,recid from contactPerson

where ( contactPerson.Email == email

|| contactPerson.Email2 == email

|| contactPerson.Email3 == email);

if(contactPerson.ContactPersonId)

{

docuref.RefRecId = contactPerson.RecId;

docuRef.RefTableId = tablenum(contactPerson);

docuref.ContactPersonId = contactPerson.ContactPersonId;

return true;

}

select firstonly RecId,ContactPersonId from custTable where custTable.Email == email;

if(custTable.AccountNum)

{

docuref.RefRecId = custTable.RecId;

docuRef.RefTableId = tablenum(custTable);

docuref.ContactPersonId = custTable.ContactPersonId;

return true;

}

}

}

return false;

}

boolean initDocuref(str _subject)

{

smmDragDropObjectType smmDragDropObjectType = smmDragDropObjectType::InMail;

;

docuRef.ActualCompanyId = curext();

docuref.AuthorId = smmUtility::getCurrentContact();

docuref.Name = _subject;

docuRef.TypeId = DocuType::findDroppedObjectType(smmDragDropObjectType);

}

boolean importEmail(str _entryId,str _storeId)

{

DocuType docuType;

DocuValue docuValue;

NumberSeq numSeq;

str tofilename;

int numOfAttachments;

FilePath archivePath;

int lines = infolog.line();

Query q;

;

if (!_entryId || !_storeId)

{

return checkFailed("@SYS87269");

}

docuType = DocuType::find(docuRef.TypeId);

// Check that the document file location isn't set to "Original location" in the document

if (docuType.FilePlace == DocuFilePlace::NoCopy)

{

// File location can not be set up to Orginal location for the Outlook mail types

return checkFailed("@SYS87271");

}

// Is archive set up to be in a Party (do not save in database)

if (smmDocuments::mustArchiveFiles(docuType))

{

// Get archive path

archivePath = docuType.ArchivePath;

if (archivePath && ! WinAPI::pathExists(archivePath))

{

q = new Query();

q.addDataSource(tablenum(DocuType)).addRange(fieldnum(DocuType,TypeId)).value(queryValue(docuType.TypeId));

return checkFailed(strfmt("@SYS90175",archivePath),'',

SysInfoAction_FormrunQuery::newFormnameControlnameQuery(

formstr(docuType),

identifierstr(Setup_ArchivePath),q));

}

// If no path to set up on the document type the general archive path is used instead

if (! archivePath)

{

archivePath = Docu::archivePath(docuType.DataAreaId);

}

}

else

{

// The Windows path is used because the Outlook mail must be written somewhere on disk as a temp file before it can be saved in the database

archivePath = WinAPI::getWindowsDirectory();

}

// Get a new number from the document numbersequence

numSeq = NumberSeq::newGetNum(DocuParameters::numRefDocuNumber(), true);

// Use next number in numbersequence as filename

docuValue.FileName = smmDocuments::getNonExistingFileName(numSeq, archivePath, 'msg');

// Save mail as the msg type file

docuValue.FileType = 'msg';

// If path doesn't end with to backslash it should be appended

archivePath = Docu::fileCheckPath(archivePath);

docuValue.Path = archivePath;

// Create filename based on the path in the document type table and the filename (number)

tofilename = docuValue.Path + docuValue.FileName + (docuValue.FileType ? ('.' + docuValue.FileType) : '');

// Save the e-mail as a .msg file

try

{

// Call save function on the Outlook mail item

mailItemClass.SaveAs(tofilename,Microsoft.Office.Interop.Outlook.OlDefaultFolders::olFolderInbox);

}

catch

{

Error('Cannot Save Mail as file');

return false;

}

// Check that the file was saved correctly

if (!archivePath || !WinAPI::fileExists(tofilename))

{

// Free the document numbersequence number that was reserved if the file wasn't found

numSeq.abort();

// The file could not be saved. Please check the path in the document type setup.

return checkFailed("@SYS86983");

}

// Create the file reference

docuValue.insert();

// Mark the document numbersequence number is used

numSeq.used();

// Create the document

docuRef.ValueRecId = docuValue.RecId;

docuRef.Notes = '';

docuRef.SmmEMailEntryID = _entryID;

docuRef.SmmEMailStoreID = _storeID;

docuRef.insert();

ttscommit;

// Should the file be stored in the Axapta database?

if (docuType.FilePlace == DocuFilePlace::Database)

{

// Copy the file to the database

docuValue = DocuValue::writeDocuValue(docuRef, tofilename);

// Delete the temp file that was placed in the Windows Party

WinAPI::deleteFile(toFileName);

}

return true;

}

- Mohammed Rasheed

www.dynamic-ax.co.uk

 

评论 (2)

请稍候...
很抱歉,您输入的评论太长。请缩短您的评论。
您没有输入任何内容,请重试。
很抱歉,我们当前无法添加您的评论。请稍后重试。
若要添加评论,需要您的家长授予您相应权限。请求权限
您的家长禁用了评论功能。
很抱歉,我们当前无法删除您的评论。请稍后重试。
您已超过了一天之内允许提供的评论数上限。请在 24 小时后重试。
因为我们的系统表明您可能在向其他用户提供垃圾评论,您的帐户已禁用了评论功能。如果您认为我们错误地禁用了您的帐户,请联系 Windows Live 支持部门
完成下面的安全检查,您提供评论的过程才能完成。
您在安全检查中键入的字符必须与图片或音频中的字符一致。

若要添加评论,请使用您的 Windows Live ID 登录(如果您使用过 Hotmail、Messenger 或 Xbox LIVE,您就拥有 Windows Live ID)。登录


还没有 Windows Live ID 吗?请注册

storm发表:

http://www.akkuliste.com/acer/aspire-5030.htm acer aspire 5030 akku
http://www.akkuliste.com/dell/latitude-d820.htm dell latitude d820 akku
http://www.akkuliste.com/acer/aspire-5050.htm acer aspire 5050 akku
http://www.akkuliste.com/acer/aspire-5550.htm acer aspire 5550 akku
http://www.akkuliste.com/acer/aspire-5570.htm acer aspire 5570 akku
http://www.akkuliste.com/acer/aspire-5580.htm acer aspire 5580 akku
http://www.akkuliste.com/acer/squ-401.htm acer squ-401 akku
http://www.akkuliste.com/acer/travelmate-4000.htm acer travelmate 4000 akku
http://www.akkuliste.com/acer/aspire-5000.htm acer aspire 5000 akku
http://www.akkuliste.com/acer/black-aspire-one-zg5.htm acer black aspire one zg5 akku
http://www.akkuliste.com/apple/a1079.htm apple a1079 akku
http://www.akkuliste.com/compaq/presario-2100.htm compaq presario 2100 akku
http://www.akkuliste.com/dell/inspiron-3800.htm dell inspiron 3800 akku
http://www.akkuliste.com/dell/w953g.htm dell w953g akku
http://www.akkuliste.com/apple/a1185-white.htm apple a1185 white akku
http://www.akkuliste.com/apple/a1185-black.htm apple a1185 black akku
http://www.akkuliste.com/dell/original-inspiron-1525.htm dell original inspiron 1525 akku
http://www.akkuliste.com/hp/dv6000.htm hp dv6000 akku
http://www.akkuliste.com/dell/original-inspiron-1526.htm dell original inspiron 1526 akku
http://www.akkuliste.com/dell/inspiron-6400.htm dell inspiron 6400 akku
http://www.akkuliste.com/dell/1501.htm dell 1501 akku
http://www.akkuliste.com/dell/e1505.htm dell e1505 akku
http://www.akkuliste.com/dell/kd476.htm dell kd476 akku
http://www.akkuliste.com/dell/d620.htm dell d620 akku
http://www.akkuliste.com/dell/d630.htm dell d630 akku
http://www.akkuliste.com/dell/312-038.htm dell 312-038 akku
http://www.akkuliste.com/dell/latitude-d620.htm dell latitude d620 akku
http://www.akkuliste.com/dell/latitude-d820.htm dell latitude d820 akku
http://www.akkuliste.com/dell/latitude-d830.htm dell latitude d830 akku
http://www.akkuliste.com/dell/inspiron-1520.htm dell inspiron 1520 akku
http://www.akkuliste.com/dell/inspiron-1720.htm dell inspiron 1720 akku
http://www.akkuliste.com/dell/vostro-1500.htm dell vostro 1500 akku
http://www.akkuliste.com/gateway/8msbg.htm gateway 8msbg akku
http://www.akkuliste.com/gateway/m680.htm gateway m680 akku
http://www.akkuliste.com/gateway/m360.htm gateway m360 akku
http://www.akkuliste.com/gateway/m460.htm gateway m460 akku
http://www.akkuliste.com/hp/nc8430.htm hp nc8430 akku
http://www.akkuliste.com/hp/dv6000.htm hp dv6000 akku
http://www.akkuliste.com/hp/hstnn-db42.htm hp hstnn-db42 akku
http://www.akkuliste.com/hp/dv9000.htm hp dv9000 akku
http://www.akkuliste.com/hp/dv9700.htm hp dv9700 akku
http://www.akkuliste.com/hp/hstnn-ib44.htm hp hstnn-ib44 akku
http://www.akkuliste.com/hp/510.htm hp 510 akku
http://www.akkuliste.com/hp/530.htm hp 530 akku
http://www.akkuliste.com/sony/vgp-bps2a.htm sony vgp-bps2a akku


http://www.akkuliste.com/sony/vgp-bps2b.htm sony vgp-bps2b akku
11 月 10 日
storm发表:


http://www.akkuliste.com/laptop-ac-adapter/samsung/samsung-19V-3.16A-60w-5.5mm-3.4mm-pin-inside.php
http://www.akkuliste.com/laptop-ac-adapter/liteon/liteon-19V-3.95A-75w-5.5mm-2.5mm.php
http://www.akkuliste.com/laptop-ac-adapter/liteon/liteon-19V-4.74A-90w-5.5mm-2.5mm.php
http://www.akkuliste.com/laptop-ac-adapter/liteon/liteon-19V-6.3A-120w-5.5mm-2.5mm.php
http://www.akkuliste.com/laptop-ac-adapter/liteon/liteon-19V-6.3A-120w-4pin-round.php
http://www.akkuliste.com/laptop-ac-adapter/liteon/liteon-19V-3.42A-65w-5.5mm-2.5mm-white.php
http://www.akkuliste.com/laptop-ac-adapter/toshiba/toshiba-15V-8A-120w-special-4-hole.php
http://www.akkuliste.com/laptop-ac-adapter/liteon/liteon-19V-4.74A-90w-5.5mm-1.7mm.php
http://www.akkuliste.com/laptop-ac-adapter/hp/hp-19V-4.74A-90w-5.5mm-2.5mm.php
http://www.akkuliste.com/laptop-ac-adapter/hp/hp-18.5V-3.5A-65w-4.8mm-1.7mm.php
http://www.akkuliste.com/laptop-ac-adapter/hp/hp-19V-4.74A-90w-4.8mm-1.7mm.php
http://www.akkuliste.com/laptop-ac-adapter/acer/acer-19V-3.42A-65w-5.5mm-2.5mm-big-head.php
http://www.akkuliste.com/laptop-ac-adapter/acer/acer-19V-3.42A-65w-5.5mm-1.5mm-small-head.php
http://www.akkuliste.com/laptop-ac-adapter/fujitsu/fujitsu-19V-4.74A-90w-5.5mm-2.5mm.php
http://www.akkuliste.com/laptop-ac-adapter/dell/dell-19V-3.16A-60w-5.5mm-2.5mm.php
http://www.akkuliste.com/laptop-ac-adapter/dell/dell-20V-3.5A-70w-horseshoe-style-special-for-dell-pa-6.php
http://www.akkuliste.com/laptop-ac-adapter/compaq/compaq-19V-4.74A-90w-5.5mm-2.5mm.php
http://www.akkuliste.com/laptop-ac-adapter/dell/dell-19.5V-3.34A-65w-7.4mm-5.0mm-with-pin-pa-12.php
http://www.akkuliste.com/laptop-ac-adapter/asus/asus-19v-3.42A-65w-5.5mm-2.5mm.php
http://www.akkuliste.com/dell/latitude-d620.htm dell latitude d620 akku
http://www.akkuliste.com/acer/as07b41.htm acer as07b41 akku
http://www.akkuliste.com/dell/xps-1330.htm dell xps 1330 akku
http://www.akkuliste.com/dell/xps-m1330.htm dell xps m1330 akku
http://www.akkuliste.com/acer/as07b42.htm acer as07b42 akku
http://www.akkuliste.com/acer/as07b72.htm acer as07b72 akku
http://www.akkuliste.com/acer/as07b52.htm acer as07b52 akku
http://www.akkuliste.com/acer/travelmate-4200.htm acer travelmate 4200 akku
http://www.akkuliste.com/acer/aspire-5100.htm acer aspire 5100 akku
http://www.akkuliste.com/dell/inspiron-6000.htm dell inspiron 6000 akku
http://www.akkuliste.com/dell/inspiron-9300.htm dell inspiron 9300 akku
http://www.akkuliste.com/toshiba/satellite-a100.htm toshiba satellite a100 akku
http://www.akkuliste.com/toshiba/satellite-m100.htm toshiba satellite m100 akku
http://www.akkuliste.com/toshiba/pa3534u-1bas.htm toshiba pa3534u-1bas akku
http://www.akkuliste.com/toshiba/PA3533U-1BAS.htm toshiba PA3533U-1BAS akku
http://www.akkuliste.com/acer/as07b32.htm acer as07b32 akku
http://www.akkuliste.com/acer/aspire-5500.htm acer aspire 5500 akku

11 月 10 日

引用通告

此日志的引用通告 URL 是:
http://dynamic-ax.spaces.live.com/blog/cns!13619E6948204DE3!411.trak
引用此项的网络日志