在嵌入式系统添加邮件发送功能---支持带SSL的GMAIL邮箱

原创 2010年04月30日 10:07:00

作者:易松华,华清远见嵌入式学院深圳中心讲师。

在嵌入式系统,特别是监控系统中,为了维护方便,当系统中发生异常事件时,我们系统需要通过网络给管理员发送日志或通过邮件方式批量升级嵌入式系统中的软件。而目前大多数的邮箱都需要支持SSL,给起嵌入式系统中添加邮件功能增加了难度,下面试图而通过openssl和ssmtp和mailx来在嵌入式系统中完成邮件发送功能,并对邮件方式批量升级嵌入式系统中的软件给出实现思路。

在嵌入式系统中实现以前,首先完成PC机上的测试(使用GMAIL邮箱):

shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp/ssmtp$ ./configure --prefix=/usr --sysconfdir=/etc --no-recursion --enable-ssl

    注意:

    这里要特别提醒一下,经过阅读代码,编译ssmtp的时候一定要加--enable-ssl选项,否则下面我们进行邮件发送的时候会出现如下的提示:
    send-mail: Server didn't like our AUTH LOGIN (530 5.7.0 Must issue a STARTTLS command first. 22sm3137556tim.16)
    Can't send mail: sendmail process failed with error code 1

shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp/ssmtp$ make
        root@ubuntun1:/home/shyi/s3c2410/fs2410/apps/ssmtp/ssmtp# make install
        /usr/bin/install -c -d -m 755 /sbin
        /usr/bin/install -c -s -m 755 ssmtp /sbin/ssmtp
        /usr/bin/install -c -d -m 755 /man/man8
        /usr/bin/install -c -m 644 ./ssmtp.8 /man/man8/ssmtp.8
        /usr/bin/install -c -d -m 755 /etc/ssmtp
        /usr/bin/install -c -m 644 ./revaliases /etc/ssmtp/revaliases
        ./generate_config /etc/ssmtp/ssmtp.conf
        Please enter the mail name of your system.
        This is the hostname portion of the address to be shown
        on outgoing news and mail messages headers.
        The default is ubuntun1, your system's host name.

Mail name [ubuntun1]:

Please enter the SMTP port number [25]:
        Configuration file /etc/ssmtp/ssmtp.conf already exists.
        root@ubuntun1:/home/shyi/s3c2410/fs2410/apps/ssmtp/ssmtp# sudo cp ssmtp /usr/sbin
        shyi@ubuntun1:~/s3c2410/fs2410/apps/mailx/mailx-12.4$ make
        root@ubuntun1:/usr/bin# which mail
        /usr/bin/mail
        root@ubuntun1:/usr/bin# mv mailx_link_to_mail mailx
        shyi@ubuntun1:~/s3c2410/fs2410/apps/mailx/mailx-12.4$ sudo cp mailx /usr/bin/mail

建立/etc/ssmtp/ssmtp.conf如下:

    root=farsightedu@gmail.com (此处请改为真实邮箱)
    mailhub=smtp.gmail.com:587
    rewriteDomain=
    hostname=smtp.gmail.com:587
    AuthUser=farsightedu@gmail.com (此处请改为真实邮箱)
    AuthPass=password (注意:此处需填写真实MAIL密码)
    FromLineOverride=YES

    # With gmail you should use this option insted of the 'UseTLS=YES'
    UseSTARTTLS=YES

    # Use SSL/TLS to send secure messages to server.
    #UseTLS=YES

    # With gmail you should use this option insted of the 'UseTLS=YES'
    #UseSTARTTLS=YES

    # Use SSL/TLS certificate to authenticate against smtp host.
    #UseTLSCert=YES

    # Use this RSA certificate.
    #TLSCert=/etc/ssl/certs/ssmtp.pem

建立/etc/ssmtp/revaliases

    # sSMTP aliases
    #
    # Format:        local_account:outgoing_address:mailhub
    #
    # Example: root:your_login@your.domain:mailhub.your.domain[:port]
    # where [:port] is an optional port number that defaults to 25.
    root:songhuayee@gmail.com:smtp.gmail.com:587
    mainuser:songhuayee@gmail.com:smtp.gmail.com:587

需要手动建立一个sendmail到ssmtp的link:

ln -s /usr/sbin/ssmtp /usr/sbin/sendmail
        ln -s /usr/lib/sendmail ../sbin/sendmail

下面进行测试:
        shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp/ssmtp$ cat ssmtp.c |mailx -s "testing ssmtp" mr.farsight@gmail.com

正常情况,等一小会后,可以看到,系统正常返回(没有提示),说明发送正常了。

登录进被发送的邮箱,我这里是mr.farsight@gmail.com,可以看到,通过SSMTP发送的邮件正常发送了。

下面我们来查看交互信息:

shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp$ echo ssmtp.conf |mailx -v -s "testing ssmtp" mr.farsight@gmail.com
        [<-] 220 mx.google.com ESMTP w12sm722711tib.10
        [->] EHLO smtp.gmail.com
        [<-] 250 ENHANCEDSTATUSCODES
        [->] STARTTLS
        [<-] 220 2.0.0 Ready to start TLS
        [->] EHLO smtp.gmail.com
        [<-] 250 ENHANCEDSTATUSCODES
        [->] AUTH LOGIN
        [<-] 334 VXNlcm5hbWU6
        [->] c29uZ2h1YXllZUBnbWFpbC5jb20=
        [<-] 334 UGFzc3dvcmQ6
        [<-] 235 2.7.0 Accepted
        [->] MAIL FROM:<shyi@>
        [<-] 250 2.1.0 OK w12sm722711tib.10
        [->] RCPT TO:<mr.farsight@gmail.com>
        [<-] 250 2.1.5 OK w12sm722711tib.10
        [->] DATA
        [<-] 354 Go ahead w12sm722711tib.10
        [->] Received: by smtp.gmail.com (sSMTP sendmail emulation); Thu, 02 Oct 2008 03:32:40 +0800
        [->] From: "shyi" <shyi@>
        [->] Date: Thu, 02 Oct 2008 03:32:40 +0800
        [->] To: mr.farsight@gmail.com
        [->] Subject: testing ssmtp
        [->] User-Agent: Heirloom mailx 12.4 7/29/08
        [->] MIME-Version: 1.0
        [->] Content-Type: text/plain; charset=us-ascii
        [->] Content-Transfer-Encoding: 7bit
        [->]
        [->] ssmtp.conf
        [->] .
        [<-] 250 2.0.0 OK 1222889566 w12sm722711tib.10
        [->] QUIT
        [<-]

引深的问题:

1.由于/etc/ssmtp/ssmtp.conf里面填了明文邮箱密码,以及ssmtp可以直接读取它,所以我们要对它们的权限使用非常小心,以免造成系统安全性问题:

(用root用户来进行测试)
        chown root:mail /etc/ssmtp/ssmtp.conf
        chmod 640 /etc/ssmtp/ssmtp.conf
        chown root:mail /usr/sbin/ssmtp
        chmod 2711 /usr/sbin/ssmtp

另外的方法参考:http://wiki.freebsd.org/SecureSSMTP(我没有实验过)

另外的一个方法可以是对/etc/ssmtp/ssmtp.conf里面的密码进行人为加密,这就需要改动原程序,添加加密代码,并使用密码生成工具来生成它。这个相对比较复杂,先不做它。

2. 系统的其他问题:

参考: http://cvs.fedora.redhat.com/viewvc/devel/ssmtp/,解析交换信息我们可以清楚看到密码被打印出来了(采用 base64编码).

不过我们的代码里面已经打过了这个PATCH。

3.实际应用中可能会需要发送附件的需求,从上面的交互过程,看到,系统简单的将它处理为: Content-Type: text/plain; charset=us-ascii, Content-Transfer-Encoding: 7bit,在真正应用的时候还需要对mailx是否具有附件发送功能进行研究(源代码下有mailx-12.4/mailx.1.html)。
        shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp/ssmtp$ cat ssmtp.conf |mailx -v -a ssmtp.c -s "testing ssmtp" mr.farsight@gmail.com

可以看到,系统正常的添加了附件。

【想法】:通过目标系统的邮件功能,可以将系统的LOG事件和系统的数据库备份定制性地通过邮件发送到管理者的邮箱中。

关于通过邮件升级的思考:

在系统中添加了mailx之后,邮件功能非常强大。

可以通过POP3或者IMAP的方法,将升级的内容通过邮件发送到指定邮箱来进行升级:

升级为了确保无误: 可以限定主题和暗送(或)操送到某一通过设置而指定邮箱,并添加签名档来确保是正确的升级邮件。

目标板上的移植:

在PC测试过程中发现,SSMTP需要使用OPENSSL。

1.移植OPENSSL

参考文章:http://doc.readmen.com/14/150334.shtml

首先在openssl目录下建议一个0.97d的Makefile的PATCH文件opensslForARM.Makefile.patch:

    --- openssl-0.9.7d.justUntaredAndConfiguredForARM/Makefile 2004-04-08 17:06:53.000000000 -0400
    +++ openssl-0.9.7d/Makefile 2004-04-08 17:10:40.000000000 -0400
    @@ -59,16 +59,18 @@
    # equal 4.
    # PKCS1_CHECK - pkcs1 tests.

    -CC= gcc
    +CCACHE= $(shell which ccache)
    +export CCACHE_PREFIX= distcc
    +CC= $(CCACHE) $(shell which arm-linux-gnu-gcc)
    #CFLAG= -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -Wuninitialized -DSHA1_ASM -DMD5_ASM -DRMD160_ASM
    CFLAG= -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall
    DEPFLAG=
    PEX_LIBS=
    -EX_LIBS=
    +EX_LIBS= -ldl
    EXE_EXT=
    ARFLAGS=
    -AR=ar $(ARFLAGS) r
    -RANLIB= /usr/bin/ranlib
    +AR=arm-linux-gnu-ar $(ARFLAGS) r
    +RANLIB= arm-linux-gnu-ranlib
    PERL= /usr/bin/perl
    TAR= tar
    TARFLAGS= --no-recursion

shyi@ubuntun1:~/s3c2410/fs2410/apps/openssl/openssl-0.9.7d$ ./Configure linux-elf-arm --prefix=/usr
        shyi@ubuntun1:~/s3c2410/fs2410/apps/openssl/openssl-0.9.7d$ patch -p1<../opensslForARM.Makefile.patch
        shyi@ubuntun1:~/s3c2410/fs2410/apps/openssl/openssl-0.9.7d$ make build-shared
        shyi@ubuntun1:~/s3c2410/fs2410/apps/openssl/openssl-0.9.7d$ make lib
        shyi@ubuntun1:~/s3c2410/fs2410/apps/openssl/openssl-0.9.7d$ arm-linux-gnu-strip *.so*

这时候我们可以看到:
        shyi@ubuntun1:~/s3c2410/fs2410/apps/openssl/openssl-0.9.7d$ ls -al lib*
        -rw-r--r-- 1 shyi shyi 1856336 2010-04-02 08:11 libcrypto.a
        lrwxrwxrwx 1 shyi shyi 14 2010-04-02 08:14 libcrypto.so -> libcrypto.so.0
        lrwxrwxrwx 1 shyi shyi 18 2010-04-02 08:14 libcrypto.so.0 -> libcrypto.so.0.9.7
        -rwxr-xr-x 1 shyi shyi 1016732 2010-04-02 08:14 libcrypto.so.0.9.7
        -rw-r--r-- 1 shyi shyi 288720 2010-04-02 08:11 libssl.a
        lrwxrwxrwx 1 shyi shyi 11 2010-04-02 08:14 libssl.so -> libssl.so.0
        lrwxrwxrwx 1 shyi shyi 15 2010-04-02 08:14 libssl.so.0 -> libssl.so.0.9.7
        -rwxr-xr-x 1 shyi shyi 835448 2010-04-02 08:14 libssl.so.0.9.7
        shyi@ubuntun1:~/s3c2410/fs2410/apps/openssl/openssl-0.9.7d$cp libssl.so* /opt/filesystem/usr/lib/ -darf

2.交叉编译SSMTP

shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp$ tar zxf ssmtp_2.62.orig.tar.gz
        shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp$ cd ssmtp/
        shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp/ssmtp$ zcat ../ssmtp_2.62-1.diff.gz |patch -p1
        shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp/ssmtp$ zcat ../ssmtp_2.62-1.diff.gz |patch -p1
        shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp/ssmtp$ cd ..; mv ssmtp ssmtp_arm;cd ssmtp_arm
        shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp/ssmtp_arm$ CC=arm-linux-gnu-gcc ./configure --host=arm-linux-gnu --prefix=/usr --sysconfdir=/etc --no-recursion --enable-ssl

修改生成的Makefile,将CFLAGS改成如下方式:

shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp/ssmtp$ make
        shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp/ssmtp$ arm-linux-gnu-strip ssmtp
        shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp/ssmtp_arm$ ls -al ssmtp

shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp/ssmtp$ sudo cp ssmtp /opt/filesystem/usr/sbin/ -f
        shyi@ubuntun1:~/s3c2410/fs2410/apps/ssmtp/ssmtp$ sudo chmod a+x /opt/filesystem/usr/sbin/ssmtp

需要手动建立一个sendmail到ssmtp的link:
        cd /opt/filesystem
        ln -s usr/sbin/ssmtp usr/sbin/sendmail

3.交叉编译mailx

shyi@ubuntun1:~/s3c2410/fs2410/apps/mailx$ mv mailx-12.4 mailx-12.4-x86/
        shyi@ubuntun1:~/s3c2410/fs2410/apps/mailx$ tar zxf mailx-12.4.tar.gz
        shyi@ubuntun1:~/s3c2410/fs2410/apps/mailx$ cd mailx-12.4
        shyi@ubuntun1:~/s3c2410/fs2410/apps/mailx/mailx-12.4$ CC=arm-linux-gnu-gcc make
        shyi@ubuntun1:~/s3c2410/fs2410/apps/mailx/mailx-12.4$ ls -al mailx
        -rwxr-xr-x 1 shyi shyi 488489 13:29 mailx
        shyi@ubuntun1:~/s3c2410/fs2410/apps/mailx/mailx-12.4$ arm-linux-gnu-strip mailx
        shyi@ubuntun1:~/s3c2410/fs2410/apps/mailx/mailx-12.4$ ls -al mailx
        -rwxr-xr-x 1 shyi shyi 421532 13:29 mailx
        shyi@ubuntun1:~/s3c2410/fs2410/apps/mailx/mailx-12.4$ sudo cp mailx /opt/filesystem/usr/sbin/
        shyi@ubuntun1:~/s3c2410/fs2410/apps/mailx/mailx-12.4$ sudo chmod a+x /opt/filesystem/usr/sbin/mailx

需要手动建立一个mail到mailx的link:

shyi@ubuntun1:/opt/filesystem$ cd /opt/filesystem
        shyi@ubuntun1:/opt/filesystem$ ln -s usr/sbin/mailx usr/sbin/mail
        shyi@ubuntun1:/opt/filesystem/usr/lib$ ln -s sendmail ../sbin/sendmail

4.目标板上测试:

# cd /etc
        # cat ntpd.conf |mailx -a issue.net -a /usr/sbin/ntpd -s "Sending from fs2410 Daemon" mr.farsight@gmail.com (贴了2个附件)

查看交换过程:

# cat ntpd.conf |mailx -v -a issue.net -a /usr/sbin/ntpd -s "testing ssmtp from fs2410" mr.farsight@gmail.com

可以看到在目标系统中增加邮件发送功能需要的存储空间为:835448 + 421532 + 23728=1280708/1024=1250KB,约1.25MB,通过重新对openssl进行configure,应该还能缩小一些存储空间。

比如,可以参照buildroot for avr32 对0.9.8g的编译,可以用如下选项: ./Configure linux-elf-arm --prefix=/usr --openssldir=/usr/lib/ssl threads shared no-idea no-mdc2 no-rc5

遗留问题:

【发现发生中文邮件的时候有问题】

cat mail_cont.txt |mailx -a /usr/sbin/ntpd -a 2008-mv4.0_for_BCM91125.ch_ -s "testing from 2410-20081007" mr.farsight@gmail.com
        # send-mail: Cannot open smtp.gmail.com:587

java实现发送邮件可多个附件内嵌图片-commons-email使用

前言        java实现发邮件功能,其实SUN在javaEE的开发包里给我们提供了相关的工具,利用 mail.jar 和 activation.jar可以实现这个功能,n年前包括我第一次实习的...
  • chenleixing
  • chenleixing
  • 2015年04月11日 13:22
  • 7022

java发送邮件带url、html

java发送邮件,内容包含URL、HTML,并且对URL中文编码,URL的有效性校验。
  • u010725245
  • u010725245
  • 2016年04月26日 23:43
  • 2909

使用两种方式,Android 发送文件到指定邮箱(带多个附件)

第一种方法,调用系统的邮件软件来发送 众所周知在Android中调用其他程序进行相关处理,都是使用的Intent。当然,Email也不例外。 在 在Android中,调用Email有三种类型的Inte...
  • zhizuyiwang
  • zhizuyiwang
  • 2016年06月02日 16:34
  • 4694

在嵌入式系统添加邮件发送功能---支持带SSL的GMAIL邮箱

在嵌入式系统,特别是监控系统中,为了维护方便,当系统中发生异常事件时,我们系统需要通过网络给管理员发送日志或通过邮件方式批量升级嵌入式系统中的软件。而目前大多数的邮箱都需要支持SSL,给起嵌入式系统中...
  • flymachine
  • flymachine
  • 2012年04月14日 11:54
  • 1624

在嵌入式系统添加邮件发送功能---支持带SSL的GMAIL邮箱

作者:易松华,华清远见嵌入式培训中心深圳中心讲师。在嵌入式系统,特别是监控系统中,为了维护方便,当系统中发生异常事件时,我们系统需要通过网络给管理员发送日志或通过邮件方式批量升级嵌入式系统中的软件。而...
  • farsight2009
  • farsight2009
  • 2011年05月05日 09:27
  • 1080

asp.net 邮件发送提醒功能(接收方包括QQ邮箱等)

1、编写一个通用的邮件发送操作类:MailHelper.cs,代码如下:using System; using System.Collections.Generic; using System.Lin...
  • taomanman
  • taomanman
  • 2014年12月21日 11:14
  • 2779

Java Socket 实现SMTP邮件发送,支持SSL/TSL

  • 2013年10月24日 11:01
  • 18KB
  • 下载

一个采用ASP.NET +C#+Gmail credentials实现邮件发送的程序例子

  • 2008年10月07日 21:50
  • 1KB
  • 下载

Intent机制及详解-调用系统功能,邮件发送方式,各种文件打开方法

> 打开Android手机安装的邮件客户端,可选择 Uri uri = Uri.parse("mailto:test@test.com"); Intent intent = new Intent(In...
  • ShareUs
  • ShareUs
  • 2016年08月04日 16:24
  • 3331

实现javaEmail邮件发送功能并带有生成的pdf附件

怎么发送邮件,并且实现pdf作为附件的功能。
  • Mars93
  • Mars93
  • 2017年07月03日 18:25
  • 447
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在嵌入式系统添加邮件发送功能---支持带SSL的GMAIL邮箱
举报原因:
原因补充:

(最多只允许输入30个字)