Существует ли общедоступный фрагмент кода Coldfusion, который надежно преобразует «исходный код» электронной почты в простой текст? - PullRequest
2 голосов
/ 21 сентября 2010

Я изменяю интерфейс на основе Coldfusion для приложения администратора listserv, чтобы отображать фрагменты недавно опубликованных сообщений на странице. Все сообщения хранятся в базе данных SQL Server 2005 на почтовом сервере listserv, и теоретически должно быть достаточно легко запрашивать последние и отображать их. Однако столбец «сообщение» таблицы, содержащей запись электронной почты, по-видимому, содержит весь «исходный код» электронной почты, в точности такой, какой он был отправлен на почтовый сервер. Он содержит контрольные коды, заголовки электронной почты и разметку. Например, часть данных сообщения, возвращаемых в запросе, может выглядеть примерно так:

This is a multi-part message in MIME format.  
------_=_NextPart_001_01CA9A9E.B2224293 Content-Type: text/plain;  
charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable  
All: =20 The correct time for Tuesday's call is 3 pm ET as noted on the agenda 

(разрывы строк добавлены для удобства чтения, на самом деле все они были в одной строке).

Когда я отображаю сообщение на сайте, я просто хочу, чтобы оно выглядело так:

All:
The correct time for Tuesday's call is 3 pm ET as noted on the agenda

Там на самом деле намного более сложные кодировки, чем в примере, который я привел. Некоторые сообщения включают вложения в кодировке Base-64 и тому подобное. Как я могу убрать весь код электронной почты и разметку и просто отобразить текст сообщения?

Я предполагаю, что кто-то должен был написать какой-то открытый код или какой-то пользовательский тег, который делает это, но мое Google-фу до сих пор меня не подводило. Спасибо.

1 Ответ

8 голосов
/ 21 сентября 2010

Вы можете использовать JavaMail, чтобы сделать это. Если то, что у вас есть в БД, это полная электронная почта, тогда вы сможете разбирать ее на составляющие биты, используя JavaMail.

Не уверен, каков ваш уровень Java, но, скорее всего, он вернет вам все необходимые элементы. Обработка сложных сообщений усложняется и требует рекурсии.

myEmailString - это ваш столбец из БД, содержащий всю необработанную электронную почту.

Результатом является структура со свойствами:

.toRecipients = array of email addresses
.ccRecipients = array of email addresses
.from = array of email addresses
.subject = string
.sentDate = date object
.receivedDate = date object
.attachments = array of {.mimeType: string, .fileName: string}
.bodyParts = {.html: array of strings, .text: array of strings}

Код (должен работать под CF8 + Java 1.6):

<cfscript>
    myStream = createObject("java","java.io.ByteArrayInputStream").init(myEmailstring.getBytes());
    // Create a java mimemessage and feed it our source inputSteam
    // Set up a fake MailSession so we can ingest emails from a file
    local.props = createObject("java", "java.util.Properties").init();
    local.props.put( javacast("string", "mail.host"), javacast("string", "smtp.somedomain.com"));
    local.props.put( javacast("string", "mail.transport.protocol"),  javacast("string", "smtp"));
    local.mailSession = createObject("java", "javax.mail.Session").getDefaultInstance(local.props,javacast("null", ""));

    local.message = createObject("java", "javax.mail.internet.MimeMessage").init(local.mailSession, myStream);

    local.recipientObj = createObject("java", "javax.mail.Message$RecipientType");

    // Set up our data structure to hold all the elements of the mail object.
    local.mailStruct = structNew();
    local.mailStruct.subject = "";
    local.mailStruct.from = "";
    local.mailStruct.toRecipients = "";
    local.mailStruct.ccRecipients = "";
    local.mailStruct.receivedDate = "";
    local.mailStruct.sentDate = "";
    local.mailStruct.attachments = arrayNew(1);
    local.mailStruct.bodyParts = structNew();
    local.mailStruct.bodyParts.html = arrayNew(1);
    local.mailStruct.bodyParts.text = arrayNew(1);


    // Handle all the header stuff.  Mostly just to: and from: at this point.
    local.mailStruct.subject = fixNull(local.message.getSubject());
    local.mailStruct.from = parseAddress(fixNull(local.message.getFrom()));
    local.mailStruct.toRecipients = parseAddress(fixNull(local.message.getRecipients(local.recipientObj.TO)));
    local.mailStruct.ccRecipients = parseAddress(fixNull(local.message.getRecipients(local.recipientObj.CC)));
    local.mailStruct.receivedDate = fixNull(local.message.getReceivedDate());
    local.mailStruct.sentDate = fixNull(local.message.getSentDate());

    // Handle the body stuff.
    parseEmailBody(local.message,local.mailStruct,#getTempDirectory()#);
</cfscript>
<cfdump var="#local.mailStruct#">

<cffunction name="parseEmailBody" output="false">
    <cfargument name="messagePart" required="true" />
    <cfargument name="mailStruct" required="true" />
    <cfargument name="attachDir" required="true" />
    <cfset var local=structNew()>
    <cfscript>
        if (arguments.messagePart.isMimeType("text/plain")) {
            // Text Body Part
            arrayAppend(arguments.mailStruct.bodyParts.text,arguments.messagePart.getContent());
        } else if (arguments.messagePart.isMimeType("text/html")) {
            // HTML Body Part
            arrayAppend(arguments.mailStruct.bodyParts.html,arguments.messagePart.getContent());
        } else {
            // this is a multipart email part.
            local.mp = arguments.messagePart.getContent();
            for(local.i=0; local.i < local.mp.getCount(); local.i++) {
                try {
                    local.part = local.mp.getBodyPart(javacast("int",local.i));
                    local.disp = local.part.getDisposition();
                    if (  isDefined("local.disp") && (UCase(local.disp)=="ATTACHMENT" || UCase(local.disp)=="INLINE") ) {
                        /* This is an attachment.  Handle accordingly */
                    } else {
                        /* This part is not a binary attachment - could be another multipart bit,
                            or could be a single part.  Either way, we need to run it through again
                            to see what it is and handle it properly.
                        */
                        parseEmailBody(local.part,arguments.mailStruct,arguments.attachDir);
                    }
                } catch (Any e) {
                    // Some error happened trying to parse part of the message.
                }
            }
        }
    </cfscript>
</cffunction>

<cffunction name="parseAddress" output="false">
    <cfargument name="addressObj" required="true" />
    <cfset var local=structNew()>
    <cfscript>
        local.addressArray = ArrayNew(1);
        if (NOT arguments.addressObj is "") {
            for (local.i=1; local.i lte arrayLen(arguments.addressObj); local.i++) {
                local.addressArray[local.i] = arguments.addressObj[local.i].getAddress();
            }
        }
        return local.addressArray;
    </cfscript>
</cffunction>

<cffunction name="fixNull" access="private" output="false">
    <cfargument name="valueToFix" default="" />
    <cfset rStr = "" />
    <cfif isDefined("arguments.valueToFix")>
        <cfset rStr = arguments.valueToFix />
    </cfif>
    <cfreturn rStr />
</cffunction>
...