PowerBuilder 7.0中实现电子邮件的收发

PowerBuilder 7.0中实现电子邮件的收发
  随着Internet的普及,网络的发展缩短了人与人之间的距离。现在,似乎每一个人都在使用电子邮件。事实上,由于她低廉的费用和传递的迅速已经在很大程度上取代了传统意义上的信件和传真。我们知道,任何一个人,无论他在什么地方只要拥有一台计算机、一个调制解调器以及一条电话线再加上一个Internet帐号就能实现上网收发电子邮件。因此,用这种方式来传递一些报表和数据一度成了许多单位解决异地数据传递的首选方法。

  那么,在PB中能否实现电子邮件的发送和传输呢?答案是肯定的。作为前沿的数据库开发工具PowerBuild自然不会忘记在她的集成里面为开发者提供一套解决办法。

  既然如此,如何来实现呢?首先,在开始之前我们先来初步领略一下程序的运行效果如何。


  我们可以看到画面上有平时我们发送的收件人,邮件标题,正文,附件等四项,这些已足够满足当前的需求了。

  在解决问题之前先来认识一下PB中有关邮件的四个对象:

  1、 邮件文件描述对象mailFileDescription:包含了邮件消息中附加文件的一些信息。

  2、 邮件消息对象mailMessage:包含了特定邮件消息的数据。其中包括我们需要的邮件接收日期,邮件主题,邮件内容,附件文件等。

  3、 邮件接收者对象mailRecipient:包含了邮件收件人的姓名,邮箱地址等数据。

  4、 邮件会话对象mailSession:用于建立MAPI会话。

  注:

  MAPI:Message API,简单的说,就是为了帮助你交互使用各种不同的信报系统开发应用程序,或者为了在你的应用程序中增加基本的电子邮件功能,Microsoft为你提供了信报应用程序接口MAPI。

  本文所介绍的方法和提供的程序就是基于这四个对象的操作来实现邮件的发送和接收。现在我们就针对邮件的发送和接收来分别做一下讨论。
爱游戏 2007-8-24 16:50
  第一部分:邮件发送

  要想成功发送一封真正有意义的邮件首先应该知道邮件的基本信息是什么,即要有收件人地址、邮件标题、邮件正文甚至附件等。从上面的基本概念介绍中我们可以知道要正确设置这些属性只有依靠邮件消息对象mailMessage。由于该对象是个PouwerBuilder的系统结构,所以我们可以像声明其他变量一样声明该对象的一个实例。例如,

  mailMessage mMsg

  声明了之后我们就可以来访问和初始化该邮件消息对象的各个属性值。

  一、 设置邮件标题

  即邮件主题,设置方法:

   mMsg.Subject = "邮件主题"

  很简单是吧,只要给邮件消息对象的Subject属性赋值就行了,它指明当前邮件的主题行,该信息显示在邮件的消息标题中。因为该属性是String类型,因此在程序中最多可以包含1024个字符,当然任何一个邮件发送者是不会在标题栏中写上这么多的字符。

  二、 撰写邮件正文

  方法:

mMsg.NoteText = "输入邮件正文…"

  关于这个属性没什么好说的,只是指明邮件的内容,但要注意前面的字符字数限制,当有正文太长的时候应该考虑用附件传送。限制的理由仅仅是因为我们在程序中用双引号进行赋值。另外,附件所带的文件我们也很容易用数据窗口来导出,并可以很方便的导入数据窗口中。

  三、 添加邮件的附件

  这可是本文的重点,我费好大的劲才将它搞定。实现方法:

mMsg.AttachmentFile[1] = mFd

  邮件消息对象mailMessage用属性AttachmentFile[]来指明当前邮件的附件。它是个邮件文件描述对象的数组形式。可以用来指明多个附件,依次存放在从下标1开始的数组变量里,例如

mMsg.AttachmentFile[1] = mFd // 指明附件一
…… // 重新设置mFd
mMsg.AttachmentFile[2] = mFd // 指明附件二
…… // 重新设置mFd
mMsg.AttachmentFile[n] = mFd // 指明附件三

  同时在指明附件之前你还必须在邮件文件描述对象mFd的属性Pathname和Filename中指定附件的具体位置和文件名。例如,

mailFileDescription mFd
mFd.Filename = "D:/Attach.Text"
mfd.Pathname = "D:/Attach.Text"

  注意这两个属性的值应该是相同的。如果按照邮件文件描述对象mailFileDescription的属性说明,把Pathname和Filename属性分别设置成如下文件路径和文件名的形式

mailFileDescription mFd
mFd.Filename = "Attach.Text"
mfd.Pathname = "D:/"

  则在调式应用程序的时候我们发现邮件发送函数总是返回-1,无论如何也发送不出去。真不知道PB的这两个属性有什么区别(要是你知道的话别忘了告诉我一声)。所以有必要提醒大家要是在编程遇到与此类似问题不妨也像这样多试试,尤其在有文件名和路径的情况下。
爱游戏 2007-8-24 16:50
  四、指明收件人邮箱地址

  邮件的标题,正文和附件这三样都设置齐全了也只是代表有了一封完整的信件,就像写信一样,邮寄的时候还必须写个信封。在这里信封就是要指明收件人的邮箱地址,这样才能让邮件能够顺利送达。在邮件消息对象中有一个Recipient[]属性,该属性的数据类型就是邮件收件者对象的一个数组,顾名思义是存放邮件的接收者信息,包括名字,地址都在里面。之所以用了数组是因为有时我们会经常的将一封邮件同时发送到几个人手里,这时就可以用不同数组下标来分别指定收件人。具体的设置如下:

mMsg.Recipient[1].Name = "收件人一"
mMsg.Recipient[2].Name = "收件人二"
mMsg.Recipient[N].Name = "…"

  看到这里,你或许会感到很奇怪,怎么只有收件人的名字并没有邮箱地址?就是这么简单,原因是你所对邮件收件者对象中的接收者名字的赋值是指通讯簿里面的收件人姓名。如果通讯簿为空,或者没有等效的用户名存在那么最终的邮件发送也是会失败的。这点还请大家要注意。

  一旦设置了收件人邮箱地址我们可以说万事具备,只欠东风了。我们有了邮件的标题,正文、附件和邮件送达地址之后,只要再为发送邮件建立一个会话,相当于建立一个通道,说的通俗点就是把信投到信箱里交给邮局,这样邮件才能顺着这个通道发送出去。这时要用到前面提到的邮件会话对象mailSession,具体代码如下:

mailSession mSes
mSes = create mailSession
mRet = mSes.mailLogon(mailNewSession!)
……
mRet = mSes.mailSend(mMsg)
mSes.mailLogoff()
DESTROY mSes

  该段代码首先用create为邮件会话对象开辟一个内存区域,然后用函数mailLongon()建立邮件会话,接着就调用发送邮件函数mailSend()发送邮件,最后当发送完毕后调用mailLongoff()关闭邮件会话。

  不过,当全部的邮件会话结束后别忘了用DESTRORY释放邮件会话对象所占用内存空间,以防止过多的无用内存被占用而导致系统崩溃。

  完整的邮件发送程序如下:

/**************** 程序代码:邮件发送 *****************/
mailSession mSes
mailReturnCode mRet
mailMessage mMsg
mailFileDescription mFd

// 创建邮件会话对象
mSes = create mailSession

// 建立邮件会话
mRet = mSes.mailLogon(mailNewSession!)
IF mRet <> mailReturnSuccess! THEN
MessageBox("邮件", '连接失败!')
RETURN
END IF

// 设置邮件消息对象的一些属性值
mMsg.Recipient[1].Name = sle_1.text // 邮件接收人名字
mMsg.Subject = sle_2.text // 邮件主题
mMsg.NoteText = mle_2.text // 邮件正文

mFd.Filename = mle_1.text // 设置附件的文件名
mfd.Pathname = mle_1.text // 设置附件的路径
mMsg.AttachmentFile[1] = mFd // 指明第一个附件

// 以下被屏蔽了
// 如果有多个附件可以遵照下面的方法来实现
//mFd.Filename = 'D:/Temp2.txt'
//mfd.Pathname = "D:/Temp2.txt"
//mMsg.AttachmentFile[2] = mFd
//
//mFd.Filename = 'D:/Temp3.txt'
//mfd.Pathname = "D:/Temp3.txt"
//mMsg.AttachmentFile[3] = mFd

// 发送邮件
mRet = mSes.mailSend(mMsg)
IF mRet <> mailReturnSuccess! THEN
MessageBox("邮件发送", '邮件没有被发出!')
RETURN
END IF

mSes.mailLogoff()
DESTROY mSes
/********************** 结束 ************************/


  好了,赶紧为你的好朋友发送一份邮件试一下。一切OK。
爱游戏 2007-8-24 16:50
  第二部分:邮件接收

  实现邮件接收和邮件发送的原理差不多,实现的方法也与邮件发送类似。我们首先要为程序声明一个邮件会话对象,像这样:

mailsession mses
mSes = create mailSession

  然后在接收邮件之前先建立邮件会话

mRet = mSes.mailLogon(mailNewSession!)

  一旦登陆成功就首先调用邮件会话函数mailGetMessages()来得到用户收件箱中的各消息标识,调用如下:

mSes.mailGetMessages()

  因为我们每天都会删除一些旧邮件和收到一些新的邮件,所以在收件箱中的邮件数目是不确定的,有时多有时少。因此,在读取邮件之前必须首先要知道在收件箱中总共有多少封邮件,只有这样才能保证每一封邮件都能被读到。

  通过查阅函数手册我们不难发现邮件会话对象中的,用于保存用户消息在收件箱中的标识的属性,即能够唯一代表一个邮件的ID号,它是个字符串数组形式。有多少个邮件标识就代表有多少封邮件。因此,如果能够知道它的数组的上界就可以得知总共有多少封邮件,这个值可以用系统提供的数组函数UpperBound()来得到,实现代码如下:

mailcount = UpperBound(mSes.MessageID[])

  知道了邮件总数我们就可以用一条循环语句依次读取每一封邮件。至于能够读取邮件的哪部分内容还要看在调用打开邮件消息函数mailReadMessage时其中代表要得到消息的那部分内容的参数是选择的什么。要是只想得到邮件消息头,即,只包含邮件标题以及其他一些附加属性,像到达日期,是否标记为已读等,就可以用"mailEnvelopeOnly!",但如果还想得到正文及附件就必须用"mailEntireMessage!"。因为本文的目的主要是为了能够在PB中使用邮件作为数据、报表的传递,而这些内容一般都是作为附件传送的,所以在下面的程序里我选用了"mailEntireMessage!"。但在使用我们发现,用"mailEntireMessage!"读取邮件时由于所要的信息量比较大,因此在读取的速度上会有一定的影响,不像用"mailEnvelopeOnly!"那么快,这点还需要你在编程时加以考虑。也因此我建议你在处理完该邮件之后应对它进行删除或归档。使得收件箱中邮件总数尽量达到最小。
爱游戏 2007-8-24 16:50
  在打开邮件消息之后我们就可以通过直接引用邮件消息对象的相关属性来得到邮件的标题,正文和附件。完整的邮件接收代码如下:

****************** 程序代码:接收邮件 *********************
/* 功能:1、完成从收件箱中读取邮件的标题,正文等信息。
2、同时,如果该邮件有附件的话还读取该附件的暂存路径
3、将取得的邮件信息依次存入到一个数据窗口中
*/
mailfiledescription mfd
mailReturnCode mret
mailsession mses
mailMessage msg
long n, mailcount, c_row

// 创建邮件会话对象
mSes = create mailSession

// 建立邮件会话
mRet = mSes.mailLogon(mailNewSession!)
IF mRet <> mailReturnSuccess! THEN
MessageBox("Mail", '注册失败.')
RETURN
END IF

mSes.mailGetMessages()
mailcount = UpperBound(mSes.MessageID[]) // 得到一共有多少封邮件
sle_1.Text = String(mailcount)

// 依次读取每一封邮件
FOR n = 1 to mailcount
mfd.pathname = ''

// 读取第N封邮件
mSes.mailReadMessage(mSes.MessageID[n], msg, mailEntireMessage! , FALSE)

// 将邮件信息添加到数据窗口中
c_row = dw_1.InsertRow(0)
dw_1.SetItem(c_row, "msgid", mSes.MessageID[n]) // 邮件标识
dw_1.SetItem(c_row, "msgdate", msg.DateReceived) // 邮件接收日期

dw_1.SetItem(c_row, "msgsubject", Left(msg.Subject, 50)) // 邮件主题
dw_1.SetItem(c_row, "notetext", Left(msg.NoteText, 50)) // 邮件正文

if UpperBound(msg.AttachmentFile[]) > 0 then mfd = msg.AttachmentFile[1]
if mfd.pathname <> "" then dw_1.SetItem(c_row, "Attach", Left(mfd.pathname, 100)) // 附件路径

NEXT
***************** 结束 *********************

  本程序也只是提供了读取邮件标题,正文的功能,对其附带的附件也只是给出了附件存放的位置并没有读取附件的内容,因此,如何将附件传送过来的数据添加到应用程序的数据库中的技术并未涉及到。最简单的方法就是通讯双方首先确定一个文件格式,像文本文件格式,Excel文件格式等等。然后程序根据约定的文件格式对数据窗口进行数据导入操作,具体的如何实现还请大家自己去试试。
爱游戏 2007-8-24 16:50
  这里需要提醒大家的是,当我们用邮件会话对象的函数mailReadMessage读取邮件消息时如果选择了mailEntireMessage!打开方式的话,那么在每次调用mailReadMessage函数时如果遇到了带有附件的邮件系统会把该邮件附件的副本保存在当前的临时目录里面,即,系统的环境变量TEMP,缺省的是C:/TEMP。因此,在你每次使用完该附件时最好把这个副本删除或着转移到指定的备份目录,否则的话会因为这些文件的存在,以后的每次调用mailReadMessage函数系统会依次把数字1,2,3…N加到副本后面从而生成具有相同内容的邮件附件文件副本。

  例如,假设有一封邮件的附件文件名为Attach.Txt,并且系统的临时目录为C:/Temp,那么在第一次使用mailReadMessage函数读取邮件信息时,在临时目录C:/Temp下就会有一个 Attach.Txt副本,当第二次使用mailReadMessage函数读取的时候,又会重新在临时目录C:/Temp生成一个名为Attach(1).Text副本文件,…,依次类推。这样不仅会造成系统硬盘资源的浪费,而且也使得原本想让程序在使用上做的更简化的设想遭到打击。因此,如果你用PB编写实现邮件读取功能的话,强烈建议你的应用程序应该能够做到在使用完一个邮件的附件之后立即将该附件在临时目录中的副本删除或转移到其他目录中。

  另外,本文所提供的方法也只是利用了PB自带的一些对象和函数,所能做到的也只是利用了OutLook提供的通讯簿和收件箱来到达接收和发送电子邮件。这在一般的应用中是足够了,但如果你想在你的应用程序中开发一个类似与OutLook功能的软件来这也是完全有可能的,可以通过调用一些API来实现,只是实现的过程复杂了点。之所以写这篇文章也只是想证明运用PowerBuilder也能开发出功能强大的应用软件,关键问题是你对PowerBuilder了解多少?

  最后,需要强调的是,由于电子邮件在传输的过程中存在着不安全的隐患,如中途被窃取,篡改等。所以如果你传送的数据对安全性要求比较高或者需要保密的话,可以对数据进行加密后再进行传输等。这属于系统安全和文件加密范围所以这里不加讨论。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值