跳转到内容

XQuery/发送电子邮件

来自维基教科书,开放的书籍,开放的世界

您希望从 XQuery 中发送电子邮件。这通常在报告运行完毕或发生关键事件(例如任务更新)时完成。

eXist 提供了一个简单的电子邮件界面。

创建邮件会话

[编辑 | 编辑源代码]
  let $mail-handle := mail:get-mail-session
  (
    <properties>
      <property name="mail.smtp.host" value="smtp.your-domain.com"/>
      <property name="mail.smtp.port" value="25"/>
      <property name="mail.smtp.auth" value="false"/>
      <property name="mail.smtp.allow8bitmime" value="true"/>
    </properties>
  )

发送电子邮件函数的格式

[编辑 | 编辑源代码]
  mail:send-email($email as element()+, $server as xs:string?, $charset as xs:string?) xs:boolean+ where $email 

电子邮件的格式如下

<mail>
   <from/>
   <reply-to/>
   <to/>
   <cc/>
   <bcc/>
   <subject/>
   <message>
     <text/>
     <xhtml/>
   </message>
   <attachment filename="" mimetype="">xs:base64Binary</attachment> 
</mail>
  $server	The SMTP server. If empty, then it tries to use the local sendmail program.
  $charset	The charset value used in the "Content-Type" message header (Defaults to UTF-8)

示例代码

[编辑 | 编辑源代码]
xquery version "1.0";

(: Demonstrates sending an email through Sendmail from eXist :)

declare namespace mail="http://exist-db.org/xquery/mail";

declare variable $message {
  <mail>
    <from>John Doe &lt;[email protected]&gt;</from>
    <to>[email protected]</to>
    <cc>[email protected]</cc>
    <bcc>[email protected]</bcc>
    <subject>A new task is waiting your approval</subject>
    <message>
      <text>A plain ASCII text message can be placed inside the text elements.</text>
      <xhtml>
           <html>
               <head>
                 <title>HTML in an e-mail in the body of the document.</title>
               </head>
               <body>
                  <h1>Testing</h1>
                  <p>Test Message 1, 2, 3</p>
               </body>
           </html>
      </xhtml>
    </message>
  </mail>
};

if ( mail:send-email($message, 'mail server', ()) ) then
  <h1>Sent Message OK :-)</h1>
else
  <h1>Could not Send Message :-(</h1>

JSON API 示例

[编辑 | 编辑源代码]

许多电子邮件服务还提供 JSON API。例如,Mandrill 提供了一个电子邮件服务,允许您每月免费发送前 12,000 封电子邮件。注册帐户后,他们会提供一个 API 密钥。该 API 密钥可与以下内容一起使用来发送电子邮件

xquery version "3.0";

module namespace mandrill="http://haptixgames.com/nosql-asset/mandrill";
import module namespace xqjson="http://xqilla.sourceforge.net/lib/xqjson";
import module namespace functx = "http://www.functx.com";
declare namespace httpclient="http://exist-db.org/xquery/httpclient";

declare variable $mandrill:message-send := 'https://mandrillapp.com/api/1.0/messages/send.json';

declare function mandrill:send($api-key as xs:string, 
                                $from-email as xs:string, 
                                $from-name as xs:string, 
                                $to-email as xs:string, 
                                $subject as xs:string,
                                $body-text as xs:string)
{
    let $email-xml := 
        <json type="object">
            <pair name="key"  type="string">{$api-key}</pair>
            <pair name="message"  type="object">
                <pair name="text"  type="string">{$body-text}</pair>
                <pair name="subject"  type="string">{$subject}</pair>
                <pair name="from_email"  type="string">{$from-email}</pair>
                <pair name="from_name"  type="string">{$from-name}</pair>
                <pair name="to"  type="array">
                    <item type="object">
                        <pair name="email"  type="string">{$to-email}</pair>
                    </item>
                </pair>
            </pair>
         </json>
    
    let $response := httpclient:post(xs:anyURI($mandrill:message-send), xqjson:serialize-json($email-xml), false(), ())
    
    return
    if($response/@statusCode/string() eq "200")
    then 
    (
        let $body := xqjson:parse-json(util:base64-decode($response/httpclient:body/text()))
        
        return
        if($body/item/pair[@name/string() eq 'status']/text() eq 'sent')
        then true()
        else false()
    )
    else false()
};

以下是上面 Mandrill 脚本的改进版本,它不使用 XQJSON 模块将 XML 消息序列化为 JSON。

xquery version "3.0";

(:~
: This module sends emails via Mandrill API.
:
: @author HaptixGames
: @version 1.0
:
:)

module namespace mandrill2="http://haptixgames.com/shared/modules/mandrill2";

import module namespace functx = "http://www.functx.com";

declare namespace httpclient="http://exist-db.org/xquery/httpclient";

(:~  
 : Creates an email message from inputs. 
 :)
declare %private function mandrill2:create-message(
    $api-key as xs:string, 
    $subject as xs:string,
    $body,
    $attachments as element(attachment)*,
    $from-email as xs:string,
    $from-name as xs:string,
    $to-addresses)
        as element(json)
{
    <mandrill>
        <key>{$api-key}</key>
        <async>false</async>
        <message>
            {
                if($body instance of element()*)
                then <html>{serialize($body)}</html>
                else <text>{$body}</text>
            }
            <subject>{$subject}</subject>
            <from_email>{$from-email}</from_email>
            <from_name>{$from-name}</from_name>
            {
                for $address in $to-addresses
                return
                    if($address instance of element(address))
                    then
                        <to>
                            <email>{$address/email/text()}</email>
                            <name>{$address/name/text()}</name>
                            <type>to</type>
                        </to>
                    else
                        <to>
                            <email>{$address}</email>
                            <type>to</type>
                        </to>
            }
            {   (: fake out serializer to write array :)
                if(count($to-addresses) eq 1)
                then <to/>
                else()
            }
            {
                if($attachments)
                then
                    (
                        for $attachment in $attachments
                        return
                            <attachments>
                                <type>{$attachment/mime-type/text()}</type>
                                <name>{$attachment/file-name/text()}</name>
                                <content>{$attachment/content/text()}</content>
                            </attachments>
                    )
                else ()
            }
            {   (: fake out serializer to write array :)
                if(count($attachments) eq 1)
                then <attachments/>
                else()
            }
        </message>
    </mandrill>
};

(:~ 
 : Executes Mandrill APi send.
 : 
 : @param $api-uri Mandrill API URI (default:https://mandrillapp.com/api/1.0/messages/send.json)
 : @param $api-key your Mandrill API key
 : @param $body xs:string or XML fragment
 : @param $attachments sequence in the form of <attachment><mime-type>text/plain</mime-type><file-name>some-file.txt</file-name><content>file-binary-content</content></attachment>...
 : @param $to-addresses sequence of xs:string email addresses or sequence of <address><email>[email protected]</email><name>some guy</name></address>...
 :)
declare function mandrill2:send(
    $api-uri as xs:anyURI,
    $api-key as xs:string,
    $from-email-name as xs:string,
    $from-email-address as xs:string,
    $subject as xs:string,
    $body,
    $attachments as element(attachment)*,
    $to-addresses) 
{
    let $message-xml :=
        mandrill2:create-message
        (
            $api-key, 
            $subject,
            $body,
            $attachments,
            $from-email-address,
            $from-email-name,
            $to-addresses
        )
   
    let $message-json :=
        util:serialize($message-xml,'method=json')
    
    let $response := 
        httpclient:post
        (
            $api-uri, 
            $message-json, 
            false(), 
            (
                <headers>
                    <header name="Content-Type" value="application/json"/>
                </headers>
            )
        )
    
    return
    if($response/@statusCode/string() eq "200")
    then true()
    else false()
};

此示例由 Chris Misztur 于 2013 年 9 月 21 日提供。

参考文献

[编辑 | 编辑源代码]
华夏公益教科书