`
lovnet
  • 浏览: 6671711 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

ASP.NET 2.0中发送电子邮件剖析

阅读更多

[转帖]ASP.NET 2.0中发送电子邮件剖析 Robot·H,2007-05-16 20:04:36

Author:xxz0618 Url:http://www.cnblogs.com/xxz0618/archive/2006/11/09/555378.aspx ----------------------------------------------------------------------- [B]一、简介[/B]   如今,电子邮件已经成为一种无所不在、异步通知和分布式的消息系统。存在许多web开发场所;其中,服务器端代码都需要生成一个电子邮件并且把它发送给指定的接收者。该电子邮件可以被发送给网点中的一些用户,通知他们有关于他们的新建用户帐户,提醒他们忘记的口令,或以邮件形式提交给他们一个清单。当然,这也可以是针对web开发者或站点管理员,提供给他们有关一个刚刚公开的未处理的异常或用户回馈的消息。

  幸好,ASP.NET使得发送电子邮件非常轻松。.NET框架版本1.x在System.Web.Mail类中包括了许多类,它们允许以编程方式通过短短的几行代码来发送一个电子邮件。尽管这个命名空间和这些类仍然存在于.NET框架2.0版本中,但是它们已经过时,你可以在System.Net.Mail命名空间中找到新的与邮件支持相关的类。

  在本文中,让我们来一起探讨System.Net.Mail命名空间中的相关类,并且分析如何从一个ASP.NET 2.0页面的code-behind类中发送一个电子邮件。我们还要在Web.config中指定中继服务器消息以及如何把这个消息应用于一些内置ASP.NET服务器控件中以便实现发送电子邮件(例如当一个用户创建一个帐户或需要一个口令提示器/重置器时)。

[B]二、探讨System.Net.Mail命名空间中的类[/B] 在System.Net.Mail命名空间中共有16个不同的类,它们都与把电子邮件发送到一个指定的简单的邮件传输协议(SMTP)服务器以便进一步提交有关。在这个命名空间中有两个核心类是:

  · MailMessage:描述一个电子邮件消息;它拥有From,To,Subject,Body等属性;

  · SmtpClient:把一个指定的MailMessage实例发送到一个指定的SMTP服务器。

  典型地,当你从一个ASP.NET 2.0页面中发送电子邮件时,你要:

  1. 创建一个MailMessage对象;

  2. 赋给它属性;

  3. 创建一个SmtpClient类实例;

  4. 指定关于使用该SMTP服务器的细节(如果它们没有在Web.config中指定);

  5. 经由SmtpClient对象的Send方法发送该MailMessage。  System.Net.Mail命名空间中的其它类还提供了更高级的电子邮件功能。例如,这些类能够用于在一个电子邮件消息中添加附件,把对象嵌入到一个电子邮件,指定SMTP服务器认证消息等;还有一些Exception的派生类用于处理SMTP特定的异常。我们会在以后的文章中来讨论这些其它类的更高级的使用情形。 [B]三、提供有关SMTP服务器的详细信息[/B]  当从Outlook或GMail中把一个电子邮件发送给一个朋友时,该电子邮件程序使用一个中继服务器建立一个连接并且发送该电子邮件消息的内容(连同其它一些消息,例如电子邮件创建日期,电子邮件格式(文本或HTML,等等),接收者,等等)。中继服务器接收该消息,然后连接到接收者的SMTP服务器并且发送该消息。一旦该消息被提交,接收者就能够(稍后)使用一种不同的协议(例如IMAP或POP3)来提取该消息。 因此,为了从一个ASP.NET页面中发送一个电子邮件,我们需要提供给SmtpClient类关于该中继服务器的消息。借助于中继服务器的主机名,你能够指定下列信息:相应的端口号(典型地使用端口25),当把你的电子邮件消息内容连接到中继服务器时是否使用SSL,以及认证证书(如果必要的话)等。作为选择,如果你可以在你的web服务器上安装一个本地SMTP服务,它可以周期性地监视一个特别的"drop-off"目录,发送出现在那个目录中的任何消息。你能够配置是否该SmtpClient类把它的电子邮件消息传送给一个单独的中继服务器或是否能通过DeliveryMethod属性把该邮件投入到一个指定的检出目录下。

SmtpClient类使用的中继服务器信息能够以编程方式通过SmtpClient类的属性指定,也可以被集中在Web.config文件中。为了使用Web.config方法,你可以在<configuration>元素内添加一个<system.net>元素。然后,添加一个包含一个<smtp>元素(其设置是在它的<network>子元素中指定的)的<mailSettings>元素。请参考如下的代码:

[CODE]

<configuration>

 <system.net> <mailSettings> <smtp> <network host="smtp.***.com" password="***" port="25" userName="***" defaultCredentials="false"/> </smtp> </mailSettings> </system.net>  <system.web> ... </system.web> </configuration> [/CODE]

只有SmtpClient属性的一个子集能够通过Web.config中的设置指定。为了定制其它的SmtpClient属性(例如EnableSsl,Timeout,等等),你可以在发送电子邮件时以编程方式设置它们 [B]四、通过回馈Web页面发送管理员电子邮件[/B]

为了说明使用MailMessage和SmtpClient类来实现发送一个电子邮件,我已经创建了一个简单的回馈页面示例。在这个页面中,用户被提示输入其电子邮件地址,他们的回馈主题和相应的回馈内容 [CODE]

<table border="0"> <tr> <td> <b>To Email:</b> </td> <td> <asp:TextBox runat="server" ID="UsersEmail" Columns="30"></asp:TextBox> </td> </tr> <tr> <td> <b>Subject:</b> </td> <td> <asp:TextBox runat="server" ID="Subject" Columns="30"> </asp:TextBox> </td> </tr> <tr> <td colspan="2"> <b>Body:</b> <br /> <asp:TextBox runat="server" ID="Body" TextMode="MultiLine" Columns="55" Rows="10"> </asp:TextBox> </td> </tr> <tr> <td colspan="2" align="center"> <asp:Button runat="server" ID="SendEmail" Text="Send" OnClick="SendEmail_Click" /> </td> </tr> </table> [/CODE]

 一旦用户提供了回馈消息并且点击了"Send Feedback"按钮,即发生一个回寄并且该按钮的Click事件激发。在该事件处理器内,一个MailMessage对象被创建,并且它的To,From,Subject和Body属性都根据用户提供的消息加以设置。在创建MailMessage对象并且填充它的属性后,该电子邮件被通过SmtpClient类的Send方法发送出去。 [CODE] protected void SendEmail_Click(object sender, EventArgs e) { String FromAddress = "***@***.com";   //(1)创建MailMessage实例 MailMessage mm = new MailMessage(FromAddress,UsersEmail.Text); mm.BodyEncoding = System.Text.Encoding.GetEncoding("gb2312"); mm.SubjectEncoding = System.Text.Encoding.GetEncoding("gb2312");   //(2)属性MailMessage赋值   mm.Subject = Subject.Text ;   mm.Body = Body.Text ;   mm.IsBodyHtml = false;   //(3)创建SmtpClient对象 SmtpClient smtp = new SmtpClient();   //(4)发送MailMessage(将使用Web.config设置)   smtp.Send(mm); } [/CODE]

[B]  五、结论[/B]

  通过进一步结合来自于ASP.NET 1.x的其它改进功能,ASP.NET 2.0中的电子邮件发送能力被进一步更新并且移动到一个新的命名空间-System.Net.Mail。在ASP.NET 2.0中,中继服务器设置能够容易地脱离ASP.NET代码,而移动到Web.config文件中,正如我们在这个示例所看到的。而且,还有对中继服务器认证更好的支持。在下篇文章中,我们将探讨更高级电子邮件使用情况,例如构造HTML格式的电子邮件,发送附件,把对象嵌入到电子邮件内,处理与SMTP/中继服务器相关的异常,等等。

-------------------------------------------------------------------------------- Robot·H,2007-05-16 20:05:46

Net2.0下发Email [code] /************************************************* * Suplier:RobotH * ReleaseDate:2007-05-16 * qq:283984419 * msn:glory_yimart@hotmail.com * Version:2.0 * pay attention: |----------dotNet2.0中 ,Microsoft推荐使用System.Net.Mail,而不使用System.Web.Mail |----------需要把 Norton Internet Email Auto Protected关闭. *************************************************/ using System; using System.Text; using System.Configuration; using System.Net; using System.Net.Mail; namespace Gtide.ShoppingMall.Common { public class SendMail { public SendMail() { } /// <summary> /// 发送邮件 /// </summary> /// <param name="formaddr">源电子邮件地址Addr。</param> /// <param name="formpros">源邮件显示名displayName</param> /// <param name="Encod">定义displayName 的字符集。</param> /// <param name="toaddr">目的电子邮件地址Addr。</param> /// <param name="topros">目的邮件显示名displayName</param> /// <param name="server">host</param> /// <param name="username"></param> /// <param name="password"></param> /// <param name="title">subject</param> /// <param name="body">body内容</param> public void GtideSendMail(string formaddr, string formpros, string Encod, string toaddr, string topros, string server, string username, string password, string title, string body) { /// new MailMessage(from,to); /// new MailAddress(address,displayname,encode_);

///create MailMessage System.Net.Mail.MailMessage message = new MailMessage(new MailAddress(formaddr, formpros, Encoding.GetEncoding(Encod)), new MailAddress(toaddr, topros, Encoding.GetEncoding(Encod))); ///create smtp emailsever SmtpClient smtp = new SmtpClient(server); NetworkCredential credential = new NetworkCredential(username, password);

///configure MailMessage message.Subject = title; message.Body = body; message.BodyEncoding = Encoding.GetEncoding(Encod); message.SubjectEncoding = Encoding.GetEncoding(Encod); message.IsBodyHtml = true;

smtp.Credentials = (ICredentialsByHost)credential;

try { smtp.Send(message); } catch (System.Net.Mail.SmtpFailedRecipientException ex) { throw new Exception(ex.Message, ex); }

} } } [/code] -------------------------------------------------------------------------------- Robot·H,2007-05-16 20:06:22

Net1.1下发Email [code] //================================================= //Suplier:RobotH // ReleaseDate:2007-05-16 // qq:283984419 // msn:glory_yimart@hotmail.com // Version:2.0 // pay attention: //----------dotNet2.0中 ,Microsoft推荐使用System.Net.Mail,而不使用System.Web.Mail //----------不需要把 Norton Internet Email Auto Protected关闭. //================================================= using System; using System.Collections.Generic; using System.Text; using System.Configuration; using System.Web; using System.Web.Mail; namespace Gtide.ShoppingMall.Common { class SendMail1 { public SendMail1() { }

/// <summary> /// 发送邮件 /// </summary> /// <param name="formaddr">源电子邮件地址Addr。</param> /// <param name="Encod">定义displayName 的字符集。</param> /// <param name="toaddr">目的电子邮件地址Addr。</param> /// <param name="server">host</param> /// <param name="username"></param> /// <param name="password"></param> /// <param name="title">subject</param> /// <param name="body">body内容</param> public void GtideSendMail(string formaddr, string Encod, string toaddr, string server, string username, string password, string title, string body) { ///create MailMessage System.Web.Mail.MailMessage message = new MailMessage();///只有无参的构造函数 /// set message Parameters message.From = formaddr; ///没有MaillAddress message.To = toaddr; message.Subject = title; message.Body = body; ///message.SubjectEncoding no message.BodyEncoding = Encoding.GetEncoding(Encod);

message.BodyFormat = System.Web.Mail.MailFormat.Html;///message.IsBodyHtml = true;

////Net2.0用NetworkCredential message.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", username); message.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", password); message.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate","1");

//System.Web.Mail.SmtpMail smtp = new SmtpMail(); ///Net2.0用SmtpClient

try { System.Web.Mail.SmtpMail.SmtpServer = server; System.Web.Mail.SmtpMail.Send(message); } catch(Exception ex) ///这里还不知道抛出什么异常,高手指点。 { throw new Exception(ex.Message, ex); }

} } }

[/code] -------------------------------------------------------------------------------- Robot·H,2007-05-16 20:20:00

[U][I][B]ASP.NET 2.0发送电子邮件全面剖析之二 [/B][/I][/U]

[B]一、简介[/B]

  在上篇中我们详细分析过,.NET框架2.0版本提供了一个新的命名空间(System.Net.Mail)和一些发送电子邮件的新类(注意:.NET框架1.x版本中提供的命名空间System.Web.Mail及相关的类仍然可以使用,以实现向后兼容性)。而且,我们还详细分析过如何使用System.Net.Mail命名空间中的MailMessage和SmtpClient类来发送简单的普通文本格式的电子邮件消息。  本篇将讨论与电子邮件相关的更高级的选项。我们要分析如何发送HTML格式的电子邮件,如何包括附件,以及当发送一个电子邮件时如何优雅地处理SMTP异常(例如无效的中继服务器凭证或如果该中继服务器处于离线状态)。

  本文假定你已经熟悉从一个ASP.NET 2.0 web页面发送简单的普通文本电子邮件;否则的话,请首先阅读本系列文章中的上篇。

[B]二、发送HTML格式的电子邮件[/B]

在ASP.NET 2.0中发送电子邮件时,我们已经看到如何发送普通文本电子邮件,这是通过把电子邮件内容赋给MailMessage类的Body属性实现的。其实,为了发送HTM格式的电子邮件,我们只要简单地把Body属性设置为要发送的HTML内容,然后把MailMessage类的IsBodyHtml属性设置为True即可。

  为了演示如何发送一个HTML格式的消息,我创建了一个示例,其名字为HtmlEmail.aspx。代码如下:

[CODE]

String FromAddress = "***@***.com"; //(1)创建MailMessage实例 MailMessage mm = new MailMessage(FromAddress, UsersEmail.Text); mm.BodyEncoding = System.Text.Encoding.GetEncoding("gb2312"); mm.SubjectEncoding = System.Text.Encoding.GetEncoding("gb2312"); //(2)属性MailMessage赋值 mm.Subject = Subject.Text; mm.Body = "<b>粗体</b>"; mm.IsBodyHtml = true; //(3)创建SmtpClient对象 SmtpClient smtp = new SmtpClient(); //(4)发送MailMessage(将使用Web.config设置) smtp.Send(mm); [/CODE]

如你所见,简单地把Body属性设置为要发送的HTML内容,并且把IsBodyHtml属性设置为True。至此,所有这些你已经完成!被发送到中继服务器的实际电子邮件内容(并且最后要到达接收者的电子邮件客户端)看上去如下所示:

粗体

  提示:观察发送到中继服务器的电子邮件内容

  观察通过SmtpClient类发送到中继服务器的实际电子邮件内容是很有趣的(如上面这样),对不对?在上篇中,我们讨论了如何配置SmtpClient类以把电子邮件发送到一个中继服务器或者把它投入到一个指定的目录下。使用第二个选择时,我们能够探讨实际的电子邮件内容。你可以检查本文代码中的Web.config文件。其中,有一个加了注释的<smtp>元素,它展示了如何配置该SmtpClient类以便把电子邮件的内容复制到一个指定的目录。

  该电子邮件客户端(假定它支持HTML格式的电子邮件)将在电子邮件内显示该HTML内容。如下图所示。

  提示:有关发送HTML格式的电子邮件的说明

  当发送HTML格式的电子邮件时,必须理解你在你的屏幕看到的HTML可能与你的接收者所看到的相当不同。大多数的电子邮件客户端都会"剔除"潜在危险的HTML内容(例如ActiveX控件等),许多用户都阻止JavaScript运行。 [B]三、包括附件[/B]

MailMessage类有一个Attachments属性,它是一个Attachment类实例的集合。你能够把web服务器上的一个现有文件附加到电子邮件消息,或使附件的内容基于一个流(Stream)。为了展示使用附件发送电子邮件,我创建了一个演示程序,其中访问者能够填充一个回馈形式的表单以便把一个电子邮件发送到管理员。然而,这个回馈表单允许访问者从他们的计算机中选择一个文件以便依附到从该web页面发送的电子邮件中(这很象基于Web的电子邮件程序,如Hotmail,GMail,等等。当发送一个电子邮件时,它们允许你附加一个你的计算机中的文件)。

  为了允许访问者从他们的计算机中附加一个文件,我们需要允许该用户把他们的计算机中的一个文件上载到web服务器。这可以使用FileUpload控件(这是ASP.NET2.0新添加的)来容易地实现。让我们来看一下这个演示程序中用于创建用户接口的声明性语法:

[CODE]

<form id="form1" runat="server"> <div> <table border="0"> <tr> <td> <b>To Email:</b> </td> <td> <asp:TextBox runat="server" ID="UsersEmail" Columns="30"></asp:TextBox> </td> </tr> <tr> <td> <b>Subject:</b> </td> <td> <asp:TextBox runat="server" ID="Subject" Columns="30"> </asp:TextBox> </td> </tr> <tr> <td> <strong>Attachment:</strong></td> <td> <asp:FileUpload ID="FileUpload1" runat="server" /></td> </tr> <tr> <td colspan="2"> <b>Body:</b> <br /> <asp:TextBox runat="server" ID="Body" TextMode="MultiLine" Columns="55" Rows="10"> </asp:TextBox> </td> </tr> <tr> <td colspan="2" align="center"> <asp:Button runat="server" ID="SendEmail" Text="Send" OnClick="SendEmail_Click" /> </td> </tr> </table> </div> </form>

[/CODE]

这个FileUpload控件生成一个<input type="file" ... />HTML元素,它在浏览器中被显示为带有一个Browse按钮的一个文本框。当被点击时,一个对话框打开以便用户能够从他们的计算机中选择一个文件。

  在填满回馈表单后,选择一个要上传的文件,并且点击"Send Feedback"按钮,则发生一个回寄,最后把选择文件的内容发送到web服务器。在"Send Feedback"按钮的点击事件处理器中,创建一个MailMessage对象,并且添加一个附件。由于该FileUpload提供一个到上传数据的Stream,所以,我们可以简单地指向在这个Stream中的新的Attachment对象。我们不需要把上传文件保存到web服务器的文件系统。

String FromAddress = "***@***.com"; //(1)创建MailMessage实例 MailMessage mm = new MailMessage(FromAddress, UsersEmail.Text); mm.BodyEncoding = System.Text.Encoding.GetEncoding("gb2312"); mm.SubjectEncoding = System.Text.Encoding.GetEncoding("gb2312"); //(2)属性MailMessage赋值 mm.Subject = Subject.Text; mm.Body = "<b>粗体</b>"; mm.IsBodyHtml = true; mm.Attachments.Add(new Attachment(FileUpload1.PostedFile.InputStream, FileUpload1.FileName)); //(3)创建SmtpClient对象 SmtpClient smtp = new SmtpClient(); //(4)发送MailMessage(将使用Web.config设置) smtp.Send(mm);

[B]四、处理SMTP异常[/B]

当从一个ASP.NET页面发送电子邮件时,如果中继服务器关闭会发生什么?如果认证信息使用无效,又会怎么样呢?在出现一个SMTP错误时,SmtpClient类将抛出一个SmtpException异常。为了较好地处理这样的问题,我们可以在发送电子邮件的代码中加入异常处理代码。如果出现一个SmtpException,则我们能够显示一个更友好的信息性的错误提示。

  在本文的下载内容中,我包括了一个演示,它允许访问者指定要使用的中继服务器以及认证信息。如果在试图发送一封电子邮件时存在一个错误,那么将显示一个客户端警告框,解释该问题。为了测试这一点,对于一个需要认证的中继服务器,你可以输入一个无效的中继服务器主机名或无效的凭证。 [CODE]

try { String FromAddress = "***@***.com"; //(1)创建MailMessage实例 MailMessage mm = new MailMessage(FromAddress, UsersEmail.Text); mm.BodyEncoding = System.Text.Encoding.GetEncoding("gb2312"); mm.SubjectEncoding = System.Text.Encoding.GetEncoding("gb2312"); //(2)属性MailMessage赋值 mm.Subject = Subject.Text; mm.Body = "<b>粗体</b>"; mm.IsBodyHtml = true; mm.Attachments.Add(new Attachment(FileUpload1.PostedFile.InputStream, FileUpload1.FileName)); //(3)创建SmtpClient对象 SmtpClient smtp = new SmtpClient(); //(4)发送MailMessage(将使用Web.config设置) smtp.Send(mm); } catch (SmtpException smtpEr) { Response.Write(string.Format("<Script Language='javascript'>alert('There was a problem in sending the email:{0}')</Script>", smtpEr.Message)); } catch (Exception err) { Response.Write(string.Format("<Script Language='javascript'>alert('There was a general problem:{0}')</Script>", err.Message)); }

[/CODE]

这段代码捕获SMTP特定的错误消息和普通的异常(例如把无效电子邮件地址赋值给MailMessage对象的To或From属性)。在任何一种情况下,显示一个客户端警告框以通知该用户有关该错误的细节信息。

[B]  五、结论[/B]

  在本文中,我们了解了如何发送HTML格式的电子邮件,使用附件发送电子邮件,以及优雅地处理在发送一个电子邮件消息中发生的异常。发送一个HTML格式的电子邮件就象在Body属性中指定HTML内容并且把IsBodyHtml属性为设置True一样地简单。真正的挑战在于,确保HTML内容能够在流行的电子邮件客户端按预期效果生成。为了把一个附件添加到一个电子邮件,只需要简单地添加一个Attachment对象到MailMessage的附件集合中。附件相应的数据可以来自于web服务器上的一个文件或来自于一个流。最后,为了处理SMTP级的异常,你可以添加使用SmtpClient类捕获SmtpException抛出的异常处理代码。

分享到:
评论

相关推荐

    ASP.NET2.0典型模块(1-16)

    代码 实现在线支付的示例 第8章(\C08) 示例描述:本章演示了如何实现电子邮件的发送和接收 JMail接收 使用第三方组件实现邮件的发送和接收示例 SimpleMail 使用ASP.NET的Net类自定义邮件...

    asp.net知识库

    ASP.NET2.0中themes、Skins轻松实现网站换肤! ASP.NET 2.0 中的代码隐藏和编译 ASP.NET 2.0 Language Swithcer and Theme Swicher 多语言转换和多样式主题转换 ASP.NET2.0 ObjectDataSource的使用详解(1) ASP.NET...

    史上最好传智播客就业班.net培训教程60G 不下会后悔

    这个项目完全按照高访问量互联网站进行设计,通过这个项目,学员不仅可以在实战中巩固对前面学习的ASP.Net、ADO.Net、WinForm等知识的掌握,还可以掌握网站防黑、缓存、SEO、静态化、搜索引擎技术、AJAX等大型互联网...

    精通正则表达式基于.NET ASP PHP JSP JavaScript

    Visual Studio 2005及以上版本、ASP.NET 2.0及以上版本 本书14~16章所附代码的调试环境 Windows家族,Apache 2.0及以上版本 PHP 5.0及以上版本 本书17~18章所附代码的调试环境 JDK6.0 Eclipse3.2+Lomboz 本书19...

    Google-Recaptcha-Asp.net:适用于Asp.net的Google Recaptcha的最新版本

    当前功能 版本2.0 版本3.0 如果ver 3评级低(0.6),则显示Recaptcha 2拼图未来功能 重定向到短信或电子邮件(两要素身份验证)什么是reCAPTCHA? reCAPTCHA是一项免费服务,可保护您的网站免受垃圾邮件和滥用的侵害...

    BugTracker.NET v3.6.2 免费版.zip

    你需要安装IIS 和ASP.NET2.0。同时 SQL Server也必须运行起来,SQL Express也可以 主要步骤 1.解压缩zip文件到一个目录 2. 创建一个IIS 虚拟目录并且指向刚才的文件夹。请查看下面的连接...

    RSS案例视频,RSS阅读器

    RSS获取信息的模式与加入邮件列表(如电子杂志和新闻邮件)获取信息有一定的相似之处,也就是可以不必登录各个提供信息的网站而通过客户端浏览方式(称为“RSS阅读器”)或者在线RSS阅读方式这些内容。例如,通过一...

    JAVA上百实例源码以及开源项目

    Java 组播组中发送和接受数据实例 3个目标文件。 Java读写文本文件的示例代码 1个目标文件。 java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密  Java非...

    JAVA上百实例源码以及开源项目源代码

    Java 组播组中发送和接受数据实例 3个目标文件。 Java读写文本文件的示例代码 1个目标文件。 java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密  Java非...

Global site tag (gtag.js) - Google Analytics