澳门新萄京官方网站-www.8455.com-澳门新萄京赌场网址

接发邮件,Mail重复发送邮件特殊案例

2019-07-28 作者:数据库网络   |   浏览(175)

在一数据库服务器(Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64))发现有个作业调用Database Mail发送邮件时,有时候出现同样的邮件发送两封的情况,经过详细检查,排除了该作业里面业务逻辑有问题的情况,确实存在重复发送邮件的情况, 检查Database Mail日志,发现在0:00~0.03报“The mail could not be sent to the recipients because of the mail server failure. (Sending Mail using Account 1 (2016-10-27T00:03:21). Exception Message: Cannot send mails to mail server”这类的错误,具体信息如下所示

SQL Server数据库邮件使用 SMTP 服务器转发邮件,允许用户配置数据库邮件,并通过存储过程 msdb.dbo.sp_send_dbmail 向特定的用户发送邮件,邮件的格式可以是文本、Excel、或HTML。数据库邮件的最大用处是向数据库运维人员及时发送异常信息,当数据库出现异常时,数据库系统可以在第一时间发送邮件通知数据库运维人员,这样便于尽快排除数据库运行的异常情况,保证数据库能够正常、持续地提供服务。 

本文涉及的内容:
1:自己制作Pop3Helper
   信件格式的处理有麻烦
2:使用现成的pop3类
   LumiSoft.Net.POP3.Client;
      有两种处理方法
3:使用IMAP收邮件
      功能似乎更多,比起pop3来。
4:SMTP发送邮件
   关于 Mailbox unavailable. The server response was: 5.7.1 Unable to relay for xx 的错误处理

YourSQLDba的翻译(九)

维护过程有一个阀值,如果他不能让一些数据库负责人知道数据库有问题。YourSQLDba自然也包括这方面

YourSQLDba依赖新的SQL2005SMTP数据库邮件。这是新的邮件模块能够让邮件发送更容易。
以前的数据库邮件需要在SQLSERVER机器上安装outlook软件

YourSQLDba负责以下几步的邮件发送,他创建下面的步骤

一个EMAIL profile,profile名字叫"YourSQLDba_EmailProfile"
数据库邮件 EMAIL ACCOUNT会被创建根据下面的规则
帐户使用匿名验证模式,不过其他的验证模式可以在安装完毕之后手动设置
默认的验证是:<machinename>.<instancename>@YourSQLDba
有必要更改邮件服务器的域名令邮件服务器能收到邮件,避免消息被反病毒软件拦截

Email server的设置已经在安装脚本的时候设定好InitialSetupOfYourSQLDba,默认端口是25
这是正常的SMTP端口号
请记得关闭防火墙或者杀毒软件,开放25端口,设置一下白名单。

Email server 管理员有不同的策略来拦截垃圾邮件

Email server 管理员有不同的策略来拦截垃圾邮件
邮件服务器只接受合法存在的地址的邮件
拒绝系统匿名SMTP,除了机器列出来的。通常你需要更新加上你的SQLSERVER机器进去ip地址列表
让SQLSERVER的邮件发送通过
允许你组织的域名通过。

YourSQLDba提供一个存储过程去诊断邮件问题。叫“DiagDbMail”这个存储过程不需要参数
他只显示三个结果
1、列出邮件错误日志
2、列出被反垃圾程序阻挡的邮件
3、列出数据库邮件引擎开启和停止的时间
一些问题例如邮件服务器的访问性或者邮件服务器的可连接会被在第一个结果的描述列里列出,并且会列出发生的时间

Messaging   

Updated : 2009-02-25

Maintenance procedure have a low value if it can't let some database responsible know that there is a problem.  YourSQLDba philosophy includes this aspect

YourSQLDba relies on new SQL 2005 SMTP Database mail.  This new mail model makes it easy to do e-mailing.  These days were it was necessary to install Outlook (Ouch!) on SQL Server machine just to get a working MAPI interface are gone.

YourSQLDba does email setup.  It creates:

a e-mail profile (nothing to do with external e-mail profile like outlook one's).  Its name is "YourSQLDba_EmailProfile".  Database mail profiles are security containers. They contains database mail e-mail accounts .  They ARE NOT real mail accounts onto a mail server.
Database mail e-mail account is create under the e-mail profile.
It just serve the purpose of specifying the e-mail server, the SMTP authentication mode to the e-mail server, and the sender identification. 
The account generated by YourSQLDba use anonymous authentication mode, but other authentication mode can be set manually after installation. 
Default sender authentication is made this way :  <machinename>.<instancename>@YourSQLDba.sql and its description is <machinename><instancename> YourSQLDba. 
Sometimes it is necessary to modify the domain so the email server will accept it, or to avoid the message to be caught by anti-spam software.
Email server contains the value specified as parameter to procedure InitialSetupOfYourSQLDba.  The port is by default 25, which is usually the SMTP port.  Beware that it could be blocked by firewall or antivirus software.  Another important mail server policy is to restrict SMTP use to send email. Worm spam often use this protocol to send spam from your domain, which turns out to become blacklisted on all servers.  Nobody wants his organization domain to become email blacklisted.

Email server admin have different policies to fight spam worm:.

Only accept mail that match a valid existing address onto the mail server.  This is not a foolproof method because SMTP sender address can be anything. It is not a requirement of SMTP protocol to have a valid address onto the mail server.
Deny systematically anonymous SMTP, except for machine listed in an exception list (IP Address usually).  Usually you need to update it to add your SQL Server machine to make it get through.  Changing SQL Server address, without adjusting mail server exception list, could indeed may stop SQL Server emails to get  through.
A second one is to allow only email that goes to your organization domain, an unpopular policy among spammers, since the target audience is no more the world, just your organization.
Only allow authenticated account to send email.  This option could be great, because usually spam worms don't necessarily get the credentials, specially non windows authenticated one.  However beware to allow SMTP email to get through with windows authentication with no more criteria.  In a windows domain everybody session is  "windows authenticated".  In that case you need to figure out if policies can by set by email account to allow/deny SMTP.  If you use windows authentication the account that start SQL Server is the account that is used for the credentials, because this is the database engine that start the email engine (DatabaseMail90.exe). 
YourSQLDba provides a stored procedure to diagnose mail problems.  It is called DiagDbMail.  It requires no parameter and simply produce three results sets:  First, it lists email error log. Second, it lists emails sent, which is a proof that email server sent it, but it was caught somewhere between you and the mail server (on the anti-spam engine), third it list of database mail engine is up and running.  Problem like mail server access or mail server communication is clearly listed in the description field of the first result sets, with a timestamp to indicate when it occurred.

 

SQL Server 并没有内置邮件服务器(Mail Server),它跟我们发送邮件一样,需要用户名和密码通过 SMTP(Simple Message Transfer Protocol)去连接邮件服务器。我们想让 SQL Server 来发送邮件,首先要告诉它用户名称,密码,服务器地址,网络传送协议,邮件服务器的端口。。。等信息。

澳门新萄京官方网站 1

一,配置数据库邮件

自己写一个POP3的接收程序并不是很简单。主要问题就是如何处理信件的格式。
其处理方法不是太复杂,用一个tcp联接就可以了。
这是代码
     public class Pop3Helper
    {
        string _pop3server;
        string _user;
        int _port;
        string _pwd;

以下脚本实现了数据库邮件的配置:
--下面是具体的配置邮件步骤
--在 sa 系统帐户下运行。

Date 2016/10/27 0:03:21

配置数据库邮件时,主要配置两个对象:Account 和 Profile,数据库账户(Account)包含SQL Server用于把邮件发送给SMTP 服务器的信息,包含外发(outgoing)的邮件地址,显示名(Display Name)以及使用SMTP服务器地址;每一个account包含一个SMTP 服务器。数据库邮件配置(Profile)是账户(Account)的有序集合,存储过程 msdb.dbo.sp_send_dbmail 或SQL Server Agent 使用Profile发送邮件,而不是直接使用Account。Profile提供邮件发送服务的自动故障转移(failover),由于一个Profile包含多个Account,当第一个Account出现故障时,Profile自动使用后续的Account发送邮件,实现邮件发送的自动故障转移。当SMTP服务器变更时,DBA只需要修改Account,而不需要修改Profile,使得编程更加灵活和可靠。

        public TcpClient _server;
        public NetworkStream _netStream;
        public StreamReader _reader;
        public string _data;
        public byte[] _charData;
        public string _CRLF = "rn";

1. 启用 SQL Server 2005 邮件功能。

use master
go
exec sp_configure 'show advanced options',1
go
reconfigure
go
exec sp_configure 'Database mail XPs',1
go
reconfigure
go

Log Database Mail (Database Mail Log)

下面的示例图展示数据库邮件的配置:3个Account,2个Profile,每个Profile都包含2个Account,

        private string _log;
        public string LogMSG
        {
            get { return _log; }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param ></param>
        /// <param ></param>
        /// <param ></param>
        /// <param ></param>
        public Pop3Helper(string server, int port, string user, string pwd)
        {
            _pop3server = server;
            _port = port;
            _user = user;
            _pwd = pwd;
        }
        /// <summary>
        /// connect
        /// </summary>
        public void Connect()
        {
            //create a tcp connection
            _server = new TcpClient(_pop3server, _port);

2. 在 SQL Server 2005 中添加邮件帐户(account)

exec msdb.dbo.sysmail_update_account_sp
@account_name ='ProjectDB',  -- 邮件帐户名称
@email_address ='projectdb@almail.e6gps.com',  -- 发件人邮件地址
@display_name ='风神项目',  -- 发件人姓名
@MAILSERVER_NAME = 'almail.e6gps.com',  -- 邮件服务器地址
@PORT =25,  -- 邮件服务器端口
@USERNAME = 'projectdb@almail.e6gps.com',  -- 用户名
@PASSWORD = 'xxxxxx'  -- 密码
GO

Log ID 29022

澳门新萄京官方网站 2

            //prepare
            _netStream = _server.GetStream();
            _reader = new StreamReader(_server.GetStream());
            if (!CheckResult(_reader.ReadLine()))
                throw new Exception("Connect Error");

3. 在 SQL Server 2005 中添加 profile

 exec msdb..sysmail_add_profile_sp @profile_name = 'DBA_Mail'      -- profile 名称
                                 ,@description  = 'DBA_Mail' -- profile 描述
                                 ,@profile_id   = null

Process ID 11300

1,打开配置数据库邮件的向导

            //login
            _data = "USER " this._user _CRLF;
            _charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());
            _netStream.Write(_charData, 0, _charData.Length);
            if (!CheckResult(_reader.ReadLine()))
                throw new Exception("User Error");

4. 在 SQL Server 2005 中映射 account 和 profile

exec msdb..sysmail_add_profileaccount_sp  @profile_name    = 'DBA_Mail' -- profile 名称
                                         ,@account_name    = 'ProjectDB'     -- account 名称
                                         ,@sequence_number = 1   

Mail Item ID 747326

在SSMS的Management目录中,右击“Database Mail”弹出快捷菜单,点击“Configure Database Mail”,打开数据库邮件配置向导 “Database Mail Configuration Wizard”,在向导界面上,选择“Set up Database Mail by performing the following tasks”选项,点击“Next”按钮,开始配置数据库邮件:

            _data = "PASS " this._pwd _CRLF;
            _charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());
            _netStream.Write(_charData, 0, _charData.Length);
            if (!CheckResult(_reader.ReadLine()))
                throw new Exception("Pass Error");

5.添加操作人

EXEC msdb.dbo.sp_add_operator @name=N'E6Project', 
        @enabled=1, 
        @weekday_pager_start_time=0, 
        @weekday_pager_end_time=235959, 
        @saturday_pager_start_time=0, 
        @saturday_pager_end_time=235959, 
        @sunday_pager_start_time=0, 
        @sunday_pager_end_time=235959, 
        @pager_days=127, 
        @email_address=N'projectdb@almail.e6gps.com', 
        @category_name=N'[Uncategorized]'

Last Modified 2016/10/27 0:03:21

澳门新萄京官方网站 3

        }
        /// <summary>
        /// get message Numbers
        /// </summary>
        /// <returns></returns>
        public int GetMailCount()
        {
            try
            {
                _data = "STAT" _CRLF;
                _charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());
                _netStream.Write(_charData, 0, _charData.Length);
                string resp = _reader.ReadLine();
                string[] tokens = resp.Split(new char[] { ' ' });
                return Convert.ToInt32(tokens[1]);
            }
            catch (Exception ex)
            {
                return 0;
            }
        }

6. 利用 SQL Server 2005 Database Mail 功能发送邮件

  exec msdb..sp_send_dbmail @profile_name =  'DBA_Mail'     -- profile 名称
                         ,@recipients   =  'projectdb@almail.e6gps.com'  -- 收件人邮箱
                         ,@subject      =  'SQL Server 2008 Mail 测试' -- 邮件标题
                         ,@body         =  'Hello Mail!测试'   -- 邮件内容
                         ,@body_format  =  'TEXT'      -- 邮件格式

--6. 查看邮件发送情况:

use msdb
go
select * from sysmail_allitems
select * from sysmail_mailitems
select * from sysmail_event_log
SELECT name FROM   msdb..sysmail_profile
SELECT name FROM   msdb.dbo.sysoperators
SELECT * FROM msdb.[dbo].[sysmail_account]

Last Modified By sa

2,创建数据库邮件配置(Profile)

        public string GetMail(int id)
        {
            string line;
            string content = "";
            try
            {
                //get by id
                _data = "RETR " id _CRLF;
                _charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());
                _netStream.Write(_charData, 0, _charData.Length);
                line = _reader.ReadLine();

异常问题

  • 如果不是以 sa 帐户发送邮件,则可能会出现错误:
    Msg 229, Level 14, State 5, Procedure sp_send_dbmail, Line 1
    EXECUTE permission denied on object 'sp_send_dbmail', database 'msdb', schema 'dbo'.
    这是因为,当前 SQL Server 登陆帐户(login),在 msdb 数据库中没有发送数据库邮件的权限,需要加入 msdb 数据库用户,并通过加入 sp_addrolemember 角色赋予权限。假设该SQL Server 登陆帐户名字为 “dba”
use msdb
go
create user dba for login dba
go
exec dbo.sp_addrolemember @rolename   = 'DatabaseMailUserRole',
                          @membername = 'dba'
go

此时,再次发送数据库邮件,仍可能有错误:
Msg 14607, Level 16, State 1, Procedure sp_send_dbmail, Line 119
profile name is not valid
虽然,数据库用户 “dba” 已经在 msdb 中拥有发送邮件的权限了,但这还不够,他还需要有使用 profile:“dba_profile” 的权限。

use msdb
go
exec sysmail_add_principalprofile_sp  @principal_name = 'dba'
                                    ,@profile_name   = 'dba_profile'
                                     ,@is_default     = 1

从上面的参数 @is_default=1 可以看出,一个数据库用户可以在多个 mail profile 拥有发送权限

Message

在发送数据库邮件之前,必须创建数据库邮件的配置(Profile),在配置中指定:邮件服务器(SMTP Server)的账户,一个数据库邮件配置可以包含多个SMTP 账户,点击“Add”按钮,添加SMTP Account:

                if (line[0] != '-')
                {
                    //end with '.'
                    while (line != ".")
                    {
                        line = _reader.ReadLine();
                        content = line "rn";
                    }
                }

The mail could not be sent to the recipients because of the mail server failure. (Sending Mail using Account 1 (2016-10-27T00:03:21). Exception Message: Cannot send mails to mail server. (Mailbox unavailable. The server response was: 5.7.1 Unable to relay for zhouxxxx@xxxx.mail.onmicrosoft.com).

澳门新萄京官方网站 4

                return content;

)

3,配置SMTP账户

            }

 

配置新添加的SMTP Account,配置数据库邮件的发送地址(E-mail Address)及其显示名称(Display Name),邮件服务器的地址(在Server Name中填写邮件服务器的URL,在Port Number中填写端口号),和身份验证(SMTP Authentication)信息:

            catch (Exception err)
            {
                Log(err.Message);
                return "Error";
            }
        }
        public void DeleteMail(int id)
        {
            _data = "DELE" id _CRLF;
            _charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());
            _netStream.Write(_charData, 0, _charData.Length);
            if (!CheckResult(_reader.ReadLine()))
                throw new Exception("Delete Error");

从上面日志可以看到是SMTP反馈zhouxxxx@xxxx.mail.onmicrosoft.com这个邮箱无法送达。Mail Item ID就可以查到相关,然后和开发人员一排查,就找到了发送邮件的存储过程,检查发现还是因为其中一个邮箱地址弄错了,导致这些错误出现在Database Mail日志中,当然如果遇到这类错误,必须查看Exception Message: Cannot send mails to mail server后面括号里面详细的报错信息,然后检查、分析确认(Mailbox unavailable. The server response was: 5.7.1 Unable to relay for zhouxxxx@xxxx.mail.onmicrosoft.com). 不同的日志信息,往往反馈不同的问题。也正是这种情况的邮件,都出现了重复发送情况。

澳门新萄京官方网站 5

        }
        /// <summary>
        /// close connection
        /// </summary>
        public void Close()
        {

 

在配置Account时,有三种SMTP验证方式,分别是Windows域账户验证、基本验证(用户名和密码)、匿名验证,大多数STMP服务器都需要账户登陆,很少有匿名验证方式。

            _data = "QUIT" _CRLF;
            _charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());
            _netStream.Write(_charData, 0, _charData.Length);

手工测试这样的情形(发送给多个收件人,其中一个邮件名称故意写错),发现邮箱确实会收到两封这样的邮件。

4,设置默认的Profile

            //close
            _netStream.Close();
            _reader.Close();
        }

EXEC msdb.dbo.sp_send_dbmail @subject='邮件重复发生问题测试——1',@recipients='xxxx@xxxx.microsoft.com;konglb@xxxx.com',@body='test the email send twice problem';

如果设置了默认的Profile,执行msdb.dbo.sp_send_dbmail 时不需要@profile_name显式指定配置名称:

        private bool CheckResult(string reply)
        {
            Log(reply);
            if (reply.IndexOf(" OK") > -1)
                return true;
            else
                return false;
        }
        private void Log(string msg)
        {
            _log = msg "rn";
        }
    }
。。。。。
但是这种方式的一个问题就是关于解析信件的格式。如果是附件的话,他也直接给出了二进制,不容易使用。
所以,可以使用一个现成的工具:LumiSoft.Net.POP3.Client。这里面已经给写好了实现,用起来也很简单。
这是一个简单的用法(这里使用了两种处理方式,前一种是不建议使用的)
。。
            using (POP3_Client pop3 = new POP3_Client())
            {
                //与Pop3服务器建立连接
                pop3.Connect(_popServer, _pop3port,false);
                //验证身份
                pop3.Authenticate(_user, _pwd, false);

 

澳门新萄京官方网站 6

                //get all messages
                POP3_MessagesInfo infos = pop3.GetMessagesInfo();
                 foreach (POP3_MessageInfo info in infos)
                {
                    byte[] bytes = pop3.GetMessage(info.MessageNumber);
                    Mime mime = Mime.Parse(bytes);
                    HandleMail(mime);
                    //delete it at last
                    //pop3.DeleteMessage(info.MessageNumber);
                }
                //the second way to do it
//for (int i = 0; i < pop3.Messages.Count; i )
                //{
                //    byte[] bytes = pop3.Messages[i].MessageToByte();
                //    Mime mime = Mime.Parse(bytes);
                //    HandleMail(mime);
                //    //delete it at last
                //    //pop3.DeleteMessage(pop3.Messages[i].SequenceNumber);
                //}。
。。。
取得的邮件可以这要给获得。
   #region pop3
            //string customer = mime.MainEntity.To.ToAddressListString();//cargo company
            //string sender = mime.MainEntity.From.ToAddressListString();//this is customer who send

 

5,发送测试邮件

            #endregion
            string customer = MailboxesToString(envelope.To);//cargo company
            string sender = MailboxesToString(envelope.From);//this is customer who send

然后我想定位到底是SQL Server版本问题,还是SMTP设置问题,结果测试过程让我更迷惑了

数据库邮件(Database Mail)自带有"Send Test E-Mail"和“View Database Mail Log”的功能,用来查看Database mail的发送情况。

。。。
除此之外,它提供的另外一个工具是IMAP,它操作起来更加方便。代码如下:

  IMAP_Client clnt = new IMAP_Client();
            try
            {
                clnt.Connect("mail.xx.com", 143, false);
                clnt.Authenticate("user", "password");
                string[] folders = clnt.GetFolders();//get all types

 

澳门新萄京官方网站 7

                string folder = "Inbox";
                clnt.SelectFolder(folder);

1: 测试了SQL Server 2008配置了同样SMTP服务器的数据库,发现这种情况,邮件不会重复发送。那么可以排除SMTP的一些设置问题导致。

 二,使用TSQL语句发送mail

                IMAP_SequenceSet sequence_set = new IMAP_SequenceSet();
                // All messages
                sequence_set.Parse(string.Format("{0}:{1}", 1, clnt.MessagesCount));

 

1,使用 msdb.dbo.sp_send_dbmail 发送mail,由于设置了default profile,所以不需要显示使用@Profile_接发邮件,Mail重复发送邮件特殊案例。Name来指定Profile。

                IMAP_FetchItem[] fetchItems = clnt.FetchMessages(
                        sequence_set,
                        IMAP_FetchItem_Flags.UID | IMAP_FetchItem_Flags.MessageFlags | IMAP_FetchItem_Flags.Size | IMAP_FetchItem_Flags.Envelope,
                        true, false
                        );
                //int count =0;
                foreach (IMAP_FetchItem fetchItem in fetchItems)
                {
                    IMAP_Envelope envelope = fetchItem.Envelope;
                    //hanldle it, means read and search and reply
                    try
                    {
                        HandleMail(envelope);
                        //count ;
                    }
                    catch (Exception ex)
                    {
                        Log("Sys", ex.Message);
                    }
                }
                //delete it after hanlde
                clnt.DeleteMessages(sequence_set, false);
                //disconnect
                clnt.Disconnect();

2: 测试了SQL Server 2014相同版本,相同SMTP配置的数据库,发现这种情况,居然不会发生邮件重复发送的情况。呐呢,让人懵了。也就是只有那台环境下才会出现这种情况,其它环境都无法重现。

EXEC msdb.dbo.sp_send_dbmail
    @recipients='xxx@domainname.com'
    ,@subject='Test email subject'
    ,@body='test email body'
    --,@profile_name='default'

                //MessageBox.Show(count.ToString() " of " fetchItems .Length " Success");
            }
            catch (Exception x)
            {
                Log("Sys", x.Message);
                //MessageBox.Show(x.Message);
            }

 

使用msdb.dbo.sp_send_dbmail也能发送HTML格式的mail,需要在参数@body_format指定格式。
[ @body_format= ] '*body_format*'

。。
上边都是如何收邮件。
关于如何发送邮件是比较简单的。这里提供两种方式。
第一种方式是使用网上的smtp。这种方式必须要提供用户名和密码。这个适合于web应用,使用的smtp也是网上的,我一般使用163的smtp,基本没有问题。
第二种方式是使用本地的smtp。不需要提供密码,用户也可以是不存在的(垃圾邮件是不是就是这么产生的?),但是必要要提供smtp端口号。
第二种方法测试的时候有时候会报错“Mailbox unavailable. The server response was: 5.7.1 Unable to relay for xxx”,查过资料之后(在baidu上没找到,还是google信息多一点),才发现问题原来是IIS里SMTP服务的配置有问题。
这样修改可以解决:到开SMTP属性—>Access页面?Reply Restrictions/ Reply-?Only this Below选项,加上自己的ip:127.0.0.1(允许本机,使用loalhost,如果是允许其他机器,类似设置)
代码如下
public class EMail
    {
        static public string accountName;
        static public string password;
        static public string smtpServer;
        static public int smtpPort;

3: 检查了Database Mail配置信息以及系统参数设置,基本一致,没有区别。也不应该是这个导致邮件重复发送问题。

默认值是Text,表示发送的是邮件正文是text格式;HTML格式,可以使用HTML 标签

        /// <summary>
        /// need password,username, smtpserver
        /// </summary>
        /// <param ></param>
        /// <param ></param>
        /// <param ></param>
        static public void SendMail(string sendTo, string subject, string body)
        {
            //.net smtp
            System.Web.Mail.MailMessage mailmsg = new System.Web.Mail.MailMessage();
            mailmsg.To = sendTo;
            //mailmsg.Cc = cc;
            mailmsg.Subject = subject;
            mailmsg.Body = body;

 

2,发送text格式的邮件

            //sender here
            mailmsg.From = EMail.accountName;
            // certify needed 
            mailmsg.Fields.Add("", "1");//1 is to certify
            //the user id  
            mailmsg.Fields.Add(
                "",
                EMail.accountName);
             //the password
            mailmsg.Fields.Add(
                "",
                 EMail.password);

4: 系统管理员帮忙检查了SMTP服务器的日志,发现重复发送的邮件除了下面Message ID不一样外,其它一样,但是检查msdb.dbo.sysmail_mailitems表里面记录,只有一条发送记录。如下截图所示

EXEC msdb.dbo.sp_send_dbmail
    @recipients='xxx@domainname.com'
    ,@subject='Test email subject'
    ,@body='test email body'
    --,@profile_name='default_ProfileName'
    --,@body_format='text'

            System.Web.Mail.SmtpMail.SmtpServer = EMail.smtpServer;
            System.Web.Mail.SmtpMail.Send(mailmsg);

澳门新萄京官方网站 8

@Body_Format 参数的默认值是Text

        }

 

3,发送Html格式的mail

        #region send mail2
        /// <summary>
        /// need username,smtp,smtp port
        /// </summary>
        /// <param ></param>
        /// <param ></param>
        /// <param ></param>
        static public void SendMail2(string sendTo, string subject, string body)
        {
            System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();
            msg.To.Add(sendTo);
            msg.From = new System.Net.Mail.MailAddress(accountName );

网上也搜索了一下,没有看到类似的问题或bug信息。真是一个非常奇怪的问题,好在这个问题解决倒非常简单。 不过问题的诡异倒是让人摸不着头脑。

declare @htmlbody varchar(max)
set @htmlbody='<table>
<tr>
    <td>first row</td>
</tr>
<tr>
    <td>second row</td>
</tr>
</table>'

EXEC msdb.dbo.sp_send_dbmail
    @recipients='xxx@domainname.com'
    ,@subject='Test email subject'
    ,@body=@htmlbody
    --,@profile_name='default_ProfileName'
    ,@body_format='Html'

            msg.Subject = subject;
            msg.SubjectEncoding = System.Text.Encoding.UTF8;
            msg.Body = body;//
            msg.BodyEncoding = System.Text.Encoding.UTF8;
            msg.IsBodyHtml = false;
            //msg.Priority = MailPriority.High;//

 

4,将查询结果作为mail的body

            System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient();
            client.Host = smtpServer;
            client.Port = smtpPort;
            //client.Credentials = new System.Net.NetworkCredential("user@xxx.com", "pass");
            client.Send(msg);

-------------------------------------------------------------------------分割线-------------------------------------------------------------------------

存储过程 msdb.dbo.sp_send_澳门新萄京官方网站,dbmail 可以执行一个select 查询子句,并将查询结果作为一个附件发送出去。

        }
        #endregion

一网友反馈出现邮件重复发送的原因是因为Database Mail Configuration里面设置为1的缘故,测试了一下,在收件人列表输入一个错误邮箱,确实会收到两封邮件。这个问题解决了!

EXEC msdb.dbo.sp_send_dbmail
    @recipients='xxx@domainname.com'
    ,@subject='Test email subject'
    --,@profile_name='default_ProfileName'
    --,@body_format='text'
    ,@query='select * from db_study.dbo.test'
    ,@attach_query_result_as_file = 1

    }

 

 

Feedback

澳门新萄京官方网站 9

参考文档:

@寒星星
这里提供的源程序已经够多了,剩下的就是你把他嵌入到自己的程序里.
其实,我也没有demo,都是从实际项目中摘出来的代码而已.

sp_send_dbmail (Transact-SQL).aspx)

用c#发送邮件,用了很长时间了,也用了不少方法,遇到不少问题.这个随笔算是一个阶段性总结了.

想知道有没有方法处理群发问题?
用for 和用mail.bcc
都有问题,特别是超时问题

LumiSoft.Net.POP3.Client

这个在哪里可以得到??

收邮件好像没这么简单,要把附件弄出来(好像要解码来的)

MailMessage 竟然无法序列化。
这样发送失败的时候想使用MessageQueue 保存都不成。还要自己定义类去保存。

邮件发送失败的后续处理这里有么。
还有邮件的缓存,有时候考虑到服务器的能力可能会缓存一些邮件。空闲的时候再发送。

希望接着写哦。

@Faster
LumiSoft.Net.POP3.Client里面是提供关于附件的解析的.如果自己作pop3,那就真得解码了.

@snoopymin
@暗香浮动

这个问题不属于纯粹的技术问题.
一般情况下,可以通过这样的方式来解决: 设置定时器,不要一次性发送过多邮件.
1:做一个ArrayList,存储发送列表.
2:然后再加一个定时器timer,5分钟执行一次.
3:在timer事件里面来发送邮件,每次发送10个,如果发送失败,就继续保留在list里面,成功则删除.

比较简单的逻辑.

这个随笔只是纯技术的.
剩下的逻辑都是额外的了,比如缓存,比如群发.
群发又有很多问题,比如定时发送,比如如何得知用户阅读情况等等.

LumiSoft其实是一个邮件服务器程序,楼主用的只是最简单的页面POP功能,他还有一个C/S的邮件收发服务器软件,也是开源的,如果配合这个,简直是无敌,不过,国外好多论坛上说这个玩意CPU占用率比较高

@梦想依旧
必须指定.就像访问网页必须要指定哪一个域名(服务器)一样.^_^

@wkcode22
功能确实不错.我用的出了pop3还有imap,不错.
其他功能没有用过,暂时还不需要.

@ithurricane
提供的代码片断已经足够多了。自己根据需要改编一下就行了。

IMAP 协议的接受邮件 你可以给我一份DEMO吗?
关键是 我看不太懂它的帮助,英文 接受后 怎么输出具体内容
例如 标题

我想知道这样用LumiSoft.Net.IMAP.Client的IMAP获取附件信息及邮件内容,希望给出代码,谢谢!!!

本文由澳门新萄京官方网站发布于数据库网络,转载请注明出处:接发邮件,Mail重复发送邮件特殊案例

关键词: