jenkins 邮件配置一
jenkins默认的邮件通知
我先讲解下,默认的。
jenkins默认就有一个邮件通知,只是太简单的,不能个性化或者说定制化。
设置系统管理员邮件地址
邮件通知
①SMTP服务器:如果你使用的是公司邮箱,那么就询问你自己公司里的运维人员吧;他们一般都知道,至少我就是问公司里的运维人员;要是你打算使用QQ邮箱,那么你需要设置下,网上有教程;网易邮箱默认开启。
说明:SMTP是一种协议
②用户默认邮件后缀:根据自己情况去设置
③勾选使用SMTP认证,用户名:根据自己情况设置,密码也是。
④SMTP端口:默认25
配置好了后,可以勾选 测试,在Test e-mail recipient输入自己的邮箱,看下能否成功。
成功后,我们可以到job中进行配置:
配置好了后,接下来测试,我下面是故意写错echo,使其构建失败,验证邮件。
发送邮件的结果:
可以看出这个邮件内容纯文本,连个超链接都没有,内容也不够丰富!
接下来我们使用增强版的邮件通知
系统配置
在安装好插件后,你的系统设置里面会有这么一个设置:
接上面图片:
上面点击高级按钮后:
①SMTP server:和之前同理
②Default user E-mail suffix:根据自己情况填写
③勾选Use SMTP Authentication,用户名和密码填写自己的
④SMTP port:默认25
⑤Default Content Type:邮件文档类型
⑥Default Recipients:默认接收人列表,已逗号进行分割
其他我都使用默认或者说没有填写,点击保存。
注意:
上面配置中,凡是以Default开头的名称,都可以在job的配置中当做变量使用。比如:默认的收件人地址:在单独的job中可以这样使用$DEFAULT_RECIPIENTS。
单个job的单独配置
在增加构建后操作步骤,添加增强版邮件通知(看红色圈住的部分):
之后你会得到:
稍微讲解下:
①Disable Extended Email Publisher:勾选后,邮件就不发送,看自己的情况喽,如果你想调试某些东西,又不想发邮件出去就可以勾选这个。
②Project Recipient List:收件人地址;多个收件人邮件地址用逗号进行分割;想使用全局默认配置的话,可以使用$DEFAULT_RECIPIENTS。
③Project Reply-To List:允许回复人的地址;想使用系统设置中的默认值的话,可以使用$DEFAULT_REPLYTO;
④Content Type:邮件文档的类型,可以设置HTML等格式;
⑤Default Subject:默认主题,也就是邮件标题;同理可以使用$DEFAULT_SUBJECT
⑥Default Content:默认邮件内容;这里是关键;我这里使用的是模板${SCRIPT, template="groovy-html.template"};后面会讲;当然不想使用模板的话,可以通过使用jenkins自身提供的变量来自己定义;
⑦Attach Build Log:发送的邮件是否包含日志;
下面几个默认就好,最后一个Triggers非常关键;
假设最后一个不改的话,邮件是接收不到的,这个是官方留下的一个大坑,一定要自己再添加一个Recipient List。
点击保存,点击构建后,收到的邮件格式如下:
遇到的问题
问题一
An attempt to send an e-mail to empty list of recipients, ignored.
- 1
这个问题,我一直卡着很久,差不多1天吧!始终不知道为什么收不到邮件
直到Google到这个地方:
https://stackoverflow.com/a/37167955/6952713
问题二
Exception raised during template rendering: No signature of method: hudson.model.FreeStyleBuild.getExactRuns() is applicable for argument types: () values: [] Possible solutions: getActions(), getActions(java.lang.Class) groovy.lang.MissingMethodException: No signature of method: hudson.model.FreeStyleBuild.getExactRuns() is applicable for argument types: () values: [] Possible solutions: getActions(), getActions(java.lang.Class) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58) at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:49) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117) at SimpleTemplateScript3.run(SimpleTemplateScript3.groovy:106) at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.writeTo(SimpleTemplateEngine.java:168) at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.toString(SimpleTemplateEngine.java:180) at hudson.plugins.emailext.plugins.content.ScriptContent.renderTemplate(ScriptContent.java:127) at hudson.plugins.emailext.plugins.content.ScriptContent.evaluate(ScriptContent.java:68) at hudson.plugins.emailext.plugins.content.AbstractEvalContent.evaluate(AbstractEvalContent.java:64) at org.jenkinsci.plugins.tokenmacro.DataBoundTokenMacro.evaluate(DataBoundTokenMacro.java:199) at
这个错误是我在使用邮件模板时,报的错!
我的步骤如下:
我在参考官方 :https://wiki.jenkins.io/display/JENKINS/Email-ext+plugin
中的Script content这一章节内容时,下载了两个Template Examples
jenkins-matrix-email-html.template
jenkins-generic-matrix-email-html.template
按照官方教程在jenkins home(/home/jenkins/dataspace)目录中创建了email-templates文件夹,并把那两个模板上传上去了,之后在job配置中的Default Content中写入:
${SCRIPT, template="jenkins-matrix-email-html.template"}
然后构建时,就报错!
这一块也困扰我很久!直到Google到了这么一段话(网上资料真心少);
http://jenkins-ci.361315.n4.nabble.com/Email-Template-Testing-Exception-td4807117.html
内容如下:
Looks like you are trying to test a matrix template with a non matrix job.
意思是说:
看起来像你在一个非
matrix job中测试一个matrix模板
之后又去查询什么是matrix job;
这是一篇关于matrix的官方教程
Building a matrix project
看到里面内容却是构建一个Multi-Configuration Projects;这时就有点迷糊了!接着查看Matrix Project Plugin这个插件;里面的讲解有这么一句话:
Multi-configuration (matrix) project type.
基本可以肯定matrix job就是Multi-configuration project(构建一个多配置项目)。也就是说我要使用jenkins-matrix-email-html.template这个模板就必须创建与之对应的job;
经过测试后,果然可以,配置都是类似的:邮件结果如下:
那么matrix job这个用的场景多吗?
这是官方给出的经验:
Experience with Hudson - Building matrix project
其讲解到:
比如 你的项目想在jdk 1.4 、1.5、1.6中进行测试,你就可以通过创建这种类型的
job;
使用自定义模板
通过上面遇到的问题,我们有时会想自己来定义模板!
使用自己的模板有两种方法:
方法一 不使用模板
在Default Content这一栏中,自己通过Token来写:
(这里的token不要翻译成令牌,因为不知道翻译成啥,就保留原文token吧)
- <!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>
- <td>
- <h2>
- <font>来自Mr.Jenkins的邮件通知</font>
- </h2>
- </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>触发原因 :${CAUSE}</li>
- <li>构建日志 : <a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
- <li>单元测试报告 :<a href="${BUILD_URL}testReport/">${BUILD_URL}testReport/</a></li>
- <li>工作目录 : <a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
- </ul>
- </td>
- </tr>
- <tr>
- <td><b><font color="#0B610B">构建日志:</font></b>
- <hr size="2" width="100%" align="center" /></td>
- </tr>
- <tr>
- <td><textarea cols="80" rows="30" readonly="readonly"
- style="font-family: Courier New">${BUILD_LOG}</textarea>
- </td>
- </tr>
- </table>
- </body>
- </html>
这段代码是从网上找来的,我好奇的是这个写法:
- ${ENV, var="JOB_NAME"}
- # 这个写法其实和${JOB_NAME}、$JOB_NAME是等价的
可以理解成:
${ENV(var:JOB_NAME)}
因为参数就一个所以可以简写为:
${JOB_NAME}或者$JOB_NAME
方法二 使用模板
之前使用模板出错是因为使用了matrix项目的模板。
如果使用groovy模板也是可以的
这是官方给的groovy的模板:
在文件夹email-templates,创建一个文件,比如我:
- //我的路径: /home/jenkins/dataspace/email-templates
- [root@master01 email-templates] vim testy.template
- // 再把官方给的模板复制粘贴进去,代码如下:
- <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>
之后把Default Content这一栏改为:
${SCRIPT, template="testy.template"}
就可以了!
可以使用Email Template Testing 这个功能进行测试,把模板名称输入进去就可以啦!
假设你输入groovy-html.template,即使你的email-templates文件夹里压根没有这个文件,也是能成功的,这是因为该插件默认内置的就是这个模板!
参考地址:
https://stackoverflow.com/questions/424295/experience-with-hudson-building-matrix-project
jenkins 邮件配置一的更多相关文章
- Jenkins学习四:Jenkins 邮件配置
本文主要对Windows环境 jenkins 的邮件通知进行介绍 jenkins 内置的邮件功能 使用email-ext插件扩展的邮件功能 邮件通知功能主要包含两个部分:全局配置和项目配置. 一. 先 ...
- jenkins 邮件配置 二 ***
Jenkins 有两种邮件通知方式: 1.Jenkins自带的“E-mail Notification” 2.插件:Extended E-mail Notification,是可编辑的邮件配置方式. ...
- jenkins邮件配置----jenkins笔记(三)
转载地址:https://www.cnblogs.com/sylvia-liu/p/4527390.html 前言 最近搭建Maven+Testng+jenkins的持续集成环境,希望最后实现自动邮件 ...
- Jenkins 邮件配置 || Jenkins 发送邮件失败,提示:Error sending to the following VALID addresses
jenkins---系统管理---系统设置 在Jenkins URL下填写URL链接 在系统管理员邮件地址下填写发件邮箱,这将是以后发送邮件通知的发件人 如果下载了外部邮件通知 配置一下SMTP se ...
- jenkins 邮件配置步骤
一.进行系统管理中的邮件配置步骤: 1.设置Extended E-mail Notification 二.对构建的job 添加邮件发送的步骤: 3.成功截图:
- jenkins邮件配置以及邮件添加附件详解
1.在系统管理-系统设置 中找到邮件配置模块 填写情况如下图 第一步,填写系统管理员邮箱 第二步,填写邮箱配置 第三步,然后在项目中添加邮箱配置 项目中邮件设置中关于附件添加 因为我的项目目录中分3 ...
- jenkins邮件配置
jenkins自带的邮件管理太弱了,为了能按自定义的方式发送邮件,需要安装一个插件: Jenkins Email Extension Plugin. 1.配置邮件:通过"系统管理&quo ...
- jenkins 邮件配置
jenkins 自带一个邮件的通知的功能,但是自带的邮件通知功能,有点简单不能自定义信息,所以我们安装邮件插件Email-ext plugin.1.首先在系统管理-插件管理-安装Email-ext p ...
- Jenkins邮件配置,实现邮件发送策略(可实现每个Job对应不同的发送邮箱)
前言: 首先,要有一个用来发送的邮箱,首选网易!参考:http://www.cnblogs.com/EasonJim/p/6051636.html,这里我注册了网易的免费企业邮箱. 并且我新建没多个邮 ...
随机推荐
- 【论文 PPT】 【转】Human-level control through deep reinforcement learning(DQN)
最近在学习强化学习的东西,在网上发现了一个关于DQN讲解的PPT,感觉很是不错,这里做下记录,具体出处不详. ============================================= ...
- 关系数据库(MySQL)的规范化、以及设计原则
1.了解范式(NF) 为了使得关系数据库能够符合规范理论,所有的数据库表都要满足:范式. 关系数据库的范式有五类:第一范式,第二范式,....第五范式.下面我们来了解一下前三个范式: 第一范式:简单来 ...
- HDU2044:一只小蜜蜂...
题目贴不上了︿( ̄︶ ̄)︿http://acm.hdu.edu.cn/showproblem.php?pid=2044 注意数据类型,用int会超范围 #include<stdio.h> ...
- 软件产品案例分析——福州大学微信小程序
一 .调研,评测 评测 第一次上手体验: 刚进入看到菜单界面,感觉还是比较生动清晰的,功能很多,也很全面,包涵了大部分学生所需要的功能,就是第一次身份验证那里找了半天. bug: 1.点击进入学生证附 ...
- HDU 1873 看病要排队 优先队列
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s) ...
- 07 Object类,Scanner,Arrays类,String类,StringBuffer类,包装类
Object类的概述:* A:Object类概述 * 类层次结构的根类 * 所有类都直接或者间接的继承自该类* B:构造方法 * public Object() * 子类的构造 ...
- 自动化-python介绍与基础
1.1-python的介绍: 简单点来说吧,python这玩意儿是一个叫做Guido van Rossum的程序猿在1989年的圣诞打发时间而决心去开发的一个脚本编程语言.它之前的名字是以abc语言的 ...
- centos7.3使用花生壳映射端口
首先下载花生壳客户端(其实我觉得更应该叫做服务端),选择相应的版本就可,例如我就是选择的linux->centos版本的 https://hsk.oray.com/download/ 我的版本为 ...
- Cassandra如何保证数据最终一致性
Cassandra如何保证数据最终一致性:1.逆熵机制(Anti-Entropy)使用默克尔树(Merkle Tree)来确认多个副本数据一致,对于不一致数据,根据时间戳来获取最新数据. 2.读修复机 ...
- oracle-pl/sql之一
http://www.cnblogs.com/huyong/archive/2011/05/10/2041951.html#_Toc15837 SQL语言只是访问.操作数据库的语言,并不是一种具有流程 ...