前言:涂涂改改,查查找找,不知不觉又三点了,废话不多说直接上教程。
准备事项:
1、安装Email Extension Plugin插件
2、安装Date Parameter插件(一个可使用的时间函数插件,没有需求的话可以不安装)
2、邮箱授权码
3、接收测试邮件的邮箱账号
注:这里就懒得改原文章了,下方教程中使用同一个授权码就好了(从头到尾用一个就行,之前了解的不太多,让之前的小伙伴入坑申请了两个授权码,不好意思了),jenkins自带的邮件通知,自带的邮件通知发送的邮件内容主要是控制台中的执行日志信息,可以和email Extension Plugin插件一起使用,不过收到的邮件就是两个了,毕竟是两个工具嘛,看个人需求使用了,一般配置email Extension Plugin插件就行。
第一步,安装Email Extension Plugin插件:
进入Jenkins的插件管理中心
点击可选插件,在搜索输入框中输入email
由于我已经安装过了,所以在可选插件中并未搜索到
插件安装方法很简单,在可选插件中勾选需要安装的插件后,点击Install without restart即可
注:Date Parameter插件安装方法同Email Extension Plugin插件安装方法(理解一下吧,百度了各种坑真心累,真的不会私聊我教你)
第二步,获取邮箱授权码:
登录进入Jenkins需要使用的用于发送邮件的邮箱web客户端,这里我使用的是网易邮箱
登录邮箱后在设置中找到POP3/SMTP/IMAP选项,点进去(其他邮箱的没有试过,不过大致流程基本都是一样的)
因为我已经配置过了,所以可以看到下方已经有了获得授权的设备,可更具自己的需求,打开IMAP协议或POP3协议。
注:IMAP或者POP3分别为不同的收信协议,您可以选择只开启需要的收信协议,比如IMAP,推荐使用IMAP协议来收发邮件,它可以和网页版完全同步。
第三步,配置Jenkins邮箱通知(此处有大坑,注意细看):
进入Jenkins依次点击Manage Jenkins、Configure System
在Jenkins Location中配置系统管理员的邮箱地址,不进行配置的话将无法发送邮件
接着 拖动页面右侧滑块到页面最底部,接着进行邮件通知的相关配置,如下图:
AuthenticationFailedException: 550 User has no permission错误,那就是授权出现了错误,此时就需要重新获取授权码再授权一次,但记得邮箱设置页面中已获得授权的设备一定要记得删除,防止自己的邮箱账号被盗
javax.mail.MessagingException: Got bad greeting from SMTP host: smtp.163.com, port: 465, response: [EOF] 错误,则查看使用的端口是否需要使用SSL协议
下面配上网易163邮箱的相关服务器信息:
最后配上配置成功后,测试邮箱获取的邮件:
很多百度的邮件收发的方法基本上都是到以上步骤就没了,哎,没错就没了,但这里有一个大坑,就是这个坑让我花了几个小时寻找解决方法,结果.........,接着看教程吧
(这个模块是用于发送构建后的报告邮件,不进行配置的话,在之后的项目构建中,你就会看到构建成功,邮件也发送成功,哎但是邮箱就是没有收到邮件,你说气不气人)
Extended E-mail Notification模块,就在邮件通知模块的上方,
注:新版本的Extended E-mail Notification配置已经没有了SMTP Username和SMTP Password配置项,取而代之的是添加凭证处理,方法如下截图:
到这配置凭证完成并成功选择添加凭证后,其他步骤就基本不变了
注意:SMTP Username中的账号一定要与系统管理员的邮箱账号保持一致
继续继续,上图邮箱界面中的效果为最终配置完以后的效果,可自行检验是否配置成功,以下任然为Extended E-mail Notification模块的配置:
附上代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
</head>
<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"
offset="0">
<table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<tr>
本邮件由系统自动发出,无需回复!<br/>
各位同事,大家好,以下为${PROJECT_NAME }项目构建信息</br>
<td><font color="#CC0000">构建结果 - ${BUILD_STATUS}</font></td>
</tr>
<tr>
<td><br />
<b><font color="#0B610B">构建信息</font></b>
<hr size="2" width="100%" align="center" /></td>
</tr>
<tr>
<td>
<ul>
<li>项目名称 : ${PROJECT_NAME}</li>
<li>构建编号 : 第${BUILD_NUMBER}次构建</li>
<li>触发原因: ${CAUSE}</li>
<li>构建状态: ${BUILD_STATUS}</li>
<li>构建日志: <a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
<li>构建 Url : <a href="${BUILD_URL}">${BUILD_URL}</a></li>
<li>工作目录 : <a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
<li>项目 Url : <a href="${PROJECT_URL}">${PROJECT_URL}</a></li>
</ul>
<h4><font color="#0B610B">失败用例</font></h4>
<hr size="2" width="100%" />
$FAILED_TESTS<br/>
<h4><font color="#0B610B">最近提交(#$SVN_REVISION)</font></h4>
<hr size="2" width="100%" />
<ul>
${CHANGES_SINCE_LAST_SUCCESS, reverse=true, format="%c", changesFormat="<li>%d [%a] %m</li>"}
</ul>
详细提交: <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a><br/>
</td>
</tr>
</table>
</body>
</html>
继续继续Extended E-mail Notification模块的配置:
勾选下图中三个触发条件:
OK,完美,完成以上步骤就可以直接保存了,接着我们继续来对项目的邮件发送进行配置
第一步,配置时间变量:
首先进入到项目配置页面中,勾选General下的This project is parameterized(这个是安装了Date Parameter插件的使用方法,没有安装的话可直接跳过这一步)
变量的应用方法例子:${date},格式为${参数名}
注:变量只能在该项目中使用,而其他项目则无法使用该变量
第二步,配置Editable Email Notification:
点击增加购进后操作步骤,选择Editable Email Notification
Project Recipient List:填入收件人的邮箱账号,有多个账号时使用逗号隔开
注:这里记录一个错误,如果出现以下错误的话,记得检查一下preject from输入框是否填写了
出现这种情况的话,检查一下 preject from输入框是否填写了,填写直接删掉,或者换成发送邮件的邮箱账号就好了,比如我的配置如下:
在preject from设置这里有一个问题,就是如果填写了完整的发送邮件账号名称,就会出现报错,报错内容为“
AuthenticationFailedException message: failed to connect, no password specified?
”但是,如果只填写发送邮件账号的前缀,后缀通过配置邮件默认后缀自动添加后缀的话就不会产生该报错信息,为了节省一些不必要的麻烦,大家还是不要填写preject from输入框了吧,让它默认为空即可,暂时不太确定是插件的bug还是对写法有特殊的限制,后期确定了会更新上最新的解决方案。
继续上面的教程,以下附上Default Content的代码(不更改的话默认使用系统配置中的格式)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
</head>
<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"
offset="0">
<h3>以下是Jenkins自动发送的邮件,请勿回复!</h3>
<div>
<table width="95%" cellpadding="0" cellspacing="0"
style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<tr>
<th><br />
<h2>构建信息</h2>
</th>
</tr>
<tr>
<td>
<ul>
<li>项目名称 : ${PROJECT_NAME}</li><br />
<li>美化的测试报告 : <a href="${PROJECT_URL}/HTML_20Summary_20Report/">${PROJECT_URL}/HTML_20Summary_20Report/</a></li><br />
<li>触发原因: ${CAUSE}</li><br />
<li>项目 Url : <a href="${PROJECT_URL}">${PROJECT_URL}</a></li><br />
</ul>
</td>
</tr>
</table>
</div>
<div>
<table>
<tr>
<th><br />
<h2>测试报告</h2>
</th>
</tr>
<tr>
<td>
<div>${FILE ,path="F:/MyTest/apache-jmeter-5.4.1/test/jmeter_report/html/接口测试简单测试报告${date}.html"}</div>
</td>
</tr>
</table>
</div>
</body>
</html>
以下代码段为你的测试报告路径:
而美化的测试报告路径,你可以更改为Jenkins中查看测试报告的页面,${PROJECT_URL}为Jenkins的项目路径,所以你只需要进入到查看报告页面,将其url的链接copy一下,就可以了
例如下方则为我的查看测试报告路径,请自行结合上面的图片对比一下,看着改吧
接着,进行邮箱附件的配置
(觉得太麻烦了,就懒得改了)
Jenkins的主目录可以在系统配置中查看,例如下图:
copy一下进入到主目录后就可以看到workspace文件夹
点进去后就可以看到你的项目还有其工作空间,而知道文件路径后,Attachments的填写方式就很简单了
为了演示创建的)
而里面有个aaa.txt文件和图片,我想作为附件发送出去的话,就可以在 Attachments中填入report/aaa.txt
这是针对单个文件的情况下,如果有多个txt文件需要作为附件进行发送,可在Attachments中填入report/*.txt
如有多个文件的话,路径之间用逗号隔开就可以了,如下图
注:其他文件类型同理,路径也同理,记得不能发送文件夹,只能发送文件,一定要发送文件夹的话,就将其压缩成一个压缩文件吧,具体方法,百度一下你知道
最后一步,构建项目:
终于到了最后一步了,配置了参数的项目,在项目管理页面中的Build now就会变成Build with Parameters,例如下图就是因为我配置一个时间参数所产生的效果
不用在意,确认参数无误后,点击开始构建即可,等待项目构建完成,你就会惊喜的发现你的邮箱中收到了你期待已久的邮件
什么情况居然说文件不存在)
上方项目中发送内容中的代码)
更改正确以后,再次点进去一看,阿西吧,怎么会有乱码。。。。。。。
这时候我们就要进行环境变量的配置了,打开系统环境变量配置窗口,添加一个系统变量
变量名为JAVA_TOOL_OPTIONS,变量值为:-Dfile.encoding=UTF-8
注意那条横杠-
紧接着,打开Jenkins系统配置页面,在全局属性中找到Environment variables并勾选上
键为:LANG,值为:zh_CN.UTF-8
处理完上述步骤后,重启Jenkins,顺便说一个重启Jenkins的方法吧,在Jenkins的url后面输入restart回车即可进入到是否重启页面
确认重启之后再次构建项目,再次查看邮箱里收到的邮件
哈哈哈,没有乱码了,但怎么有失败的。。。。。。。。。
好了以上就是忙了大半天的成果分享给大家,希望大家能避免很多不必要的坑吧。
最后附上Windows中Jenkins判断报告中是否存在失败用例的方法,以及一些避免不必要的坑的方法:Windows中Jenkins判断测试用例是否执行失
补充:
有细心的小伙伴一定发现了我的项目中有一个Email Template Testing,进入后的页面就是这个样的:
该功能为查看收到的邮件样式,使用方法为在Jenkins的主目录创建一个名为email-templates的文件夹,然后在里面创建一个文本文档,在文档中放入以下代码:
<STYLE>
BODY, TABLE, TD, TH, P {
font-family:Verdana,Helvetica,sans serif;
font-size:11px;
color:black;
}
h1 { color:black; }
h2 { color:black; }
h3 { color:black; }
TD.bg1 { color:white; background-color:#0000C0; font-size:120% }
TD.bg2 { color:white; background-color:#4040FF; font-size:110% }
TD.bg3 { color:white; background-color:#8080FF; }
TD.test_passed { color:blue; }
TD.test_failed { color:red; }
TD.console { font-family:Courier New; }
</STYLE>
<BODY>
<TABLE>
<TR><TD align="right"><IMG SRC="${rooturl}static/e59dfe28/images/32x32/<%= (build.result == null || build.result.toString() == 'SUCCESS') ? "blue.gif" : build.result.toString() == 'FAILURE' ? 'red.gif' : 'yellow.gif' %>" />
</TD><TD valign="center"><B style="font-size: 200%;">BUILD ${build.result ?: 'SUCCESSFUL'}</B></TD></TR>
<TR><TD>URL</TD><TD><A href="${rooturl}${build.url}">${rooturl}${build.url}</A></TD></TR>
<TR><TD>Project:</TD><TD>${project.name}</TD></TR>
<TR><TD>Date:</TD><TD>${it.timestampString}</TD></TR>
<TR><TD>Duration:</TD><TD>${build.durationString}</TD></TR>
<TR><TD>Cause:</TD><TD><% build.causes.each() { cause -> %> ${cause.shortDescription} <% } %></TD></TR>
</TABLE>
<BR/>
<!-- CHANGE SET -->
<% def changeSets = build.changeSets
if(changeSets != null) {
def hadChanges = false %>
<TABLE width="100%">
<TR><TD class="bg1" colspan="2"><B>CHANGES</B></TD></TR>
<% changeSets.each() { cs_list ->
cs_list.each() { cs ->
hadChanges = true %>
<TR>
<TD colspan="2" class="bg2"> Revision <B><%= cs.metaClass.hasProperty('commitId') ? cs.commitId : cs.metaClass.hasProperty('revision') ? cs.revision :
cs.metaClass.hasProperty('changeNumber') ? cs.changeNumber : "" %></B> by
<B><%= cs.author %>: </B>
<B>(${cs.msgAnnotated})</B>
</TD>
</TR>
<% cs.affectedFiles.each() { p -> %>
<TR>
<TD width="10%"> ${p.editType.name}</TD>
<TD>${p.path}</TD>
</TR>
<% }
}
}
if(!hadChanges) { %>
<TR><TD colspan="2">No Changes</TD></TR>
<% } %>
</TABLE>
<BR/>
<% } %>
<!-- ARTIFACTS -->
<% def artifacts = build.artifacts
if(artifacts != null && artifacts.size() > 0) { %>
<TABLE width="100%">
<TR><TD class="bg1"><B>BUILD ARTIFACTS</B></TD></TR>
<TR>
<TD>
<% artifacts.each() { f -> %>
<li>
<a href="${rooturl}${build.url}artifact/${f}">${f}</a>
</li>
<% } %>
</TD>
</TR>
</TABLE>
<BR/>
<% } %>
<!-- MAVEN ARTIFACTS -->
<%
try {
def mbuilds = build.moduleBuilds
if(mbuilds != null) { %>
<TABLE width="100%">
<TR><TD class="bg1"><B>BUILD ARTIFACTS</B></TD></TR>
<%
try {
mbuilds.each() { m -> %>
<TR><TD class="bg2"><B>${m.key.displayName}</B></TD></TR>
<% m.value.each() { mvnbld ->
def artifactz = mvnbld.artifacts
if(artifactz != null && artifactz.size() > 0) { %>
<TR>
<TD>
<% artifactz.each() { f -> %>
<li>
<a href="${rooturl}${mvnbld.url}artifact/${f}">${f}</a>
</li>
<% } %>
</TD>
</TR>
<% }
}
}
} catch(e) {
// we don't do anything
} %>
</TABLE>
<BR/>
<% }
}catch(e) {
// we don't do anything
}
%>
<!-- JUnit TEMPLATE -->
<% def junitResultList = it.JUnitTestResult
try {
def cucumberTestResultAction = it.getAction("org.jenkinsci.plugins.cucumber.jsontestsupport.CucumberTestResultAction")
junitResultList.add(cucumberTestResultAction.getResult())
} catch(e) {
//cucumberTestResultAction not exist in this build
}
if (junitResultList.size() > 0) { %>
<TABLE width="100%">
<TR><TD class="bg1" colspan="2"><B>${junitResultList.first().displayName}</B></TD></TR>
<% junitResultList.each{
junitResult -> %>
<% junitResult.getChildren().each { packageResult -> %>
<TR><TD class="bg2" colspan="2"> Name: ${packageResult.getName()} Failed: ${packageResult.getFailCount()} test(s), Passed: ${packageResult.getPassCount()} test(s), Skipped: ${packageResult.getSkipCount()} test(s), Total: ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()} test(s)</TD></TR>
<% packageResult.getFailedTests().each{ failed_test -> %>
<TR bgcolor="white"><TD class="test_failed" colspan="2"><B><li>Failed: ${failed_test.getFullName()} </li></B></TD></TR>
<% }
}
} %>
</TABLE>
<BR/>
<%
} %>
<!-- CONSOLE OUTPUT -->
<% if(build.result==hudson.model.Result.FAILURE) { %>
<TABLE width="100%" cellpadding="0" cellspacing="0">
<TR><TD class="bg1"><B>CONSOLE OUTPUT</B></TD></TR>
<% build.getLog(100).each() { line -> %>
<TR><TD class="console">${org.apache.commons.lang.StringEscapeUtils.escapeHtml(line)}</TD></TR>
<% } %>
</TABLE>
<BR/>
<% } %>
</BODY>
注:百度的,据说是官方给的代码,咱也不知道,能用就行了
将代码放入文件中后将文件名更改为testy.template,如下图:
完成以后就可以在Email Template Testing界面中使用了,如图
(由于,该测试模板与发送邮件所使用的不是同一个模板,所以效果显示不同,有能力的小伙伴可以自己将测试模板改一下)
好了这次是真的完了
存在什么不足的地方,欢迎联系我,谢谢
YX9010_0@的第五篇文章
2021/08/17