JustEmails
Start free trial
Tutorials··14 min read

Jenkins SMTP Setup: Build Notification Emails via JustEmails

Jenkins SMTP is configured in two separate places that share nothing. Here's how to wire both so build failures actually reach a human.

By JustEmails Platform Team
Contents
  1. What We're Building
  2. Prerequisites
  3. Step 1: Create a Dedicated Mailbox
  4. Step 2: Set the System Admin E-mail Address First
  5. Step 3: Configure the Built-In E-mail Notification
  6. Step 4: Configure Extended E-mail Notification Separately
  7. Step 5: Send Notifications From a Pipeline
  8. Step 6: The Reply-To Convention
  9. Common Jenkins SMTP Errors and How to Fix Them
  10. Advanced: Pin It in Configuration as Code
  11. Next Steps
  12. Frequently Asked Questions
  13. Why does Jenkins have two separate email configurations?
  14. How do I test Jenkins SMTP settings without running a build?
  15. Why do my Jenkins build emails go to spam?
  16. Should I use the Mailer plugin or the Email Extension plugin?
  17. Try JustEmails

The build went red at 2:14 on a Thursday. We found out the following Tuesday. The Jenkins SMTP config was the reason.

Jenkins had email configured. Sort of. Someone had typed an SMTP hostname into the E-mail Notification box eighteen months earlier, ticked nothing else, hit Save, and moved on with their life. Every send since then had been failing authentication. Quietly. The post-build mail step writes its failure into the build console and then lets the build finish green — so unless you're in the habit of reading console output on passing builds, and nobody is, you never find out.

Then there's the second problem, the one this post really exists for. The job that mattered wasn't using the built-in mailer at all. It used the Email Extension plugin, which has its own entirely separate SMTP configuration — same settings page, several screens further down. Fill in one, the other stays empty. The symptom is maddening: your test email arrives fine, your actual build notifications never do.

By the end of this you'll have Jenkins sending build alerts through JustEmails SMTP — both systems wired, authentication proven with a real test send, and a Reply-To convention that means a failure email lands somewhere a human will actually answer.

What We're Building

A Jenkins controller that:

  • Authenticates to JustEmails SMTP on port 587 with STARTTLS
  • Has both the Mailer plugin and the Email Extension plugin configured against the same mailbox
  • Sends from your own domain, with SPF and DKIM passing
  • Fires on failure, and on the first green build after a failure (not on every success — more on that below)
  • Keeps the SMTP password in Jenkins Credentials instead of in a job config

Mailboxes are unlimited on the $49/year plan, so a dedicated jenkins@yourdomain.com costs nothing extra. On per-seat providers a bot mailbox is another seat, and I have sat in a budget meeting arguing that a robot deserves one. Lost, too. So CI mail went out from a real person's account for a year, which is how build alerts end up buried three folders deep under someone's meeting invites.

Prerequisites

  • Jenkins 2.4xx LTS or newer, with admin access to Manage Jenkins
  • The Email Extension Plugin installed (Manage Jenkins → Plugins → Available). Mailer is usually already there
  • A JustEmails account with your domain added — the custom domain setup guide covers adding a domain and confirming the DNS records land
  • Outbound port 587 open from the controller, not the agents

That last point trips people up. It tripped me up. Jenkins sends mail from the controller process, always, even when the build ran on an agent in a different network — which I discovered after spending most of a Wednesday opening port 587 outbound on six build agents, feeling extremely methodical about it, for a problem that lived entirely on a machine I hadn't touched.

Step 1: Create a Dedicated Mailbox

In your JustEmails dashboard, create jenkins@yourdomain.com. Grab:

  • Host: smtp.justemails.app
  • Port: 587 (STARTTLS)
  • Username: the full address — jenkins@yourdomain.com, not jenkins
  • Password: the mailbox password

Implicit TLS on 465 works too — the breakdown of ports 25, 465, 587, and 993 sorts out which one your setup wants. For Jenkins, stay on 587. Not because 465 is worse at anything, but because the Use SSL and Use TLS checkboxes on this particular settings page are laid out in a way that makes ticking the wrong one feel like the obvious move.

Now store the password properly. Manage Jenkins → Credentials → System → Global credentials → Add Credentials. Kind: Username with password. Give it an ID you'll remember — justemails-smtp. Email Extension references credentials by ID, so a sensible name saves you scrolling a dropdown of forty entries later.

Step 2: Set the System Admin E-mail Address First

Manage Jenkins → System → Jenkins Location.

There's a field called System Admin e-mail address. Out of the box it says address not configured yet <nobody@nowhere>. That string is not a placeholder — Jenkins will genuinely put it in the From header and genuinely try to send mail as it.

Set it to:

Jenkins [jenkins@yourdomain.com](mailto:jenkins@yourdomain.com)

Do this before anything else. Half the "Jenkins SMTP doesn't work" threads I've read end with someone discovering their From address was nobody@nowhere the whole time. The handshake succeeds, the message gets refused at the data phase, and the error text is vague enough that you go hunting for a TLS problem that doesn't exist.

Step 3: Configure the Built-In E-mail Notification

Same page, scroll down to E-mail Notification. This is the Mailer plugin.

FieldValue
SMTP serversmtp.justemails.app
Default user e-mail suffix@yourdomain.com
Use SMTP Authentication (Advanced)
User Namejenkins@yourdomain.com
Passwordyour mailbox password
Use SSL
Use TLS
SMTP Port587
Reply-To Addressbuild-alerts@yourdomain.com
CharsetUTF-8

About that Default user e-mail suffix field: it tells Jenkins to email <jenkins-username>@yourdomain.com when a job notifies "culprits" — whoever committed to the broken build. Convenient right up until your Git author names don't match your Jenkins usernames, at which point Jenkins cheerfully sends failure notices to addresses that don't exist. Leave it set, but don't make culprit notification your only channel.

Then click Advanced and tick Test configuration by sending test e-mail. Put your own address in, hit Test configuration, and watch what happens without leaving the page. Success prints Email was successfully sent. Failure dumps the raw Java exception straight into the page — genuinely useful, because you get the actual SMTP response code rather than a sanitised "something went wrong".

Save. Then check the test mail actually arrived, because "successfully sent" means the server accepted it, not that it survived the trip.

Step 4: Configure Extended E-mail Notification Separately

Here's the part people miss.

Keep scrolling the same page until you hit Extended E-mail Notification. It's a completely independent config block. Nothing from Step 3 carries over. Not the host, not the port, not the credentials, not the TLS checkboxes. Nothing.

Fill it in:

FieldValue
SMTP serversmtp.justemails.app
SMTP Port587
Credentials (Advanced)justemails-smtp
Use TLS
Default user E-mail suffix@yourdomain.com
Default Content TypePlain Text (text/plain)
Default Recipientsbuild-alerts@yourdomain.com
Reply To Listbuild-alerts@yourdomain.com
Default TriggersFailure - Any, Fixed

Note that Email Extension uses the credentials store rather than inline username and password fields — that changed in the 2.x releases, and older tutorials still show the inline boxes. Confusing if you're following a 2021 blog post on a 2026 install.

This section has its own test-email field. Use it. Passing the Mailer test proves nothing about Email Extension, and vice versa.

On Default Content Type — plain text, everywhere, and I'll defend that to anyone who wants the argument. HTML build emails look great in exactly one place, Gmail's web client, and fall apart in every terminal mail reader, every Slack email-to-channel bridge, and most mobile previews. A failure alert needs four things: job name, build number, URL, last chunk of the log. Plain text gets all four onto a phone screen at 2am. The branded HTML template gets you a logo and a horizontal rule.

One more setting: Enable Debug Mode, near the bottom. It dumps the entire JavaMail SMTP conversation into the Jenkins system log. Ugly, verbose, and the fastest way to tell whether a failure is auth, TLS, or a rejected recipient. On during setup, off after.

Step 5: Send Notifications From a Pipeline

A declarative pipeline with emailext:

pipeline {
  agent any
  options { timestamps() }

  stages {
    stage('Build') { steps { sh './gradlew build' } }
    stage('Test')  { steps { sh './gradlew test' } }
  }

  post {
    failure {
      emailext(
        subject: "FAILED: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
        body: """Branch: ${env.BRANCH_NAME}
Commit: ${env.GIT_COMMIT}
Console: ${env.BUILD_URL}console

Last 50 lines:
\${BUILD_LOG, maxLines=50}
""",
        to: 'build-alerts@yourdomain.com',
        replyTo: 'build-alerts@yourdomain.com',
        from: 'Jenkins [jenkins@yourdomain.com](mailto:jenkins@yourdomain.com)',
        mimeType: 'text/plain',
        attachLog: true,
        compressLog: true,
        recipientProviders: [culprits(), requestor()]
      )
    }

    fixed {
      emailext(
        subject: "FIXED: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
        body: "Back to green after ${env.BUILD_NUMBER}. ${env.BUILD_URL}",
        to: 'build-alerts@yourdomain.com',
        replyTo: 'build-alerts@yourdomain.com',
        mimeType: 'text/plain'
      )
    }
  }
}

Two things to point at.

post { fixed { ... } } only fires when this build succeeded and the previous one failed. That's the pattern I'd argue for: alert on breakage, alert on recovery, stay quiet for the other ninety-odd percent of green builds. Emailing every success trains people to filter the thread into a folder they never open — and then you're back to finding out about Thursday's breakage on Tuesday.

\${BUILD_LOG, maxLines=50} is an Email Extension token, not a Groovy variable. The backslash stops Groovy interpolating it so the plugin can expand it at send time. Miss it and you get a groovy.lang.MissingPropertyException instead of an email. (Ask me how I know. Twice, same afternoon, two different jobs.)

Freestyle jobs use the Editable Email Notification post-build action instead — same plugin, clicked rather than typed. We've covered the equivalent setup for GitHub Actions SMTP and GitLab CI pipeline notifications if you're running more than one platform.

Step 6: The Reply-To Convention

Small thing. Saves real time.

From should be the bot: jenkins@yourdomain.com. Reply-To should be a mailbox a human reads.

Why bother? Because failure emails get forwarded. Someone hits reply-all to ask "is this the migration or the flaky test?" and that reply needs to reach the team, not a mailbox nobody has opened since March. With a no-reply From and no Reply-To, the question just evaporates.

The convention that's worked for us:

  • Fromjenkins@yourdomain.com, one address for every job
  • Reply-To — the owning team alias, overridden per job where ownership differs
  • Release and deploy pipelines — Reply-To goes to the on-call rotation alias instead

Make those real mailboxes, not forwarding-only aliases. Forwarding-only aliases are a false economy — the thread scatters across four personal inboxes and none of them is searchable by the person writing the postmortem three weeks later. A real mailbox keeps it in one place. And at $49/year flat with unlimited mailboxes, there isn't a cost argument left to hide behind.

Common Jenkins SMTP Errors and How to Fix Them

javax.mail.AuthenticationFailedException: 535 Authentication failed

Username isn't the full email address. It needs to be jenkins@yourdomain.com, not jenkins. The second most common cause is dumber — a trailing space copied along with the password — and I have burned more hours on that one invisible character than on every real TLS problem I've ever had put together. Re-paste it. I still don't check my pastes.

Could not connect to SMTP host: smtp.justemails.app, port: 587; response: -1

TLS mismatch. You've ticked Use SSL while the port says 587. Use SSL is for implicit TLS on 465; port 587 wants Use TLS (STARTTLS). Pick one pairing and make it consistent across both config blocks.

Test email works, build emails never arrive

You configured one block, not both. Go back to Step 4. This is the single most common Jenkins mail failure and it has nothing to do with SMTP.

Emails arrive from address not configured yet <nobody@nowhere>

System Admin e-mail address is still at its default. Step 2.

groovy.lang.MissingPropertyException: No such property: BUILD_LOG

You wrote ${BUILD_LOG, maxLines=50} without escaping the dollar sign inside a double-quoted Groovy string. Use \${BUILD_LOG, maxLines=50}, or switch the body to single quotes.

Emails arrive but land in spam

SPF or DKIM isn't passing for your From domain. View the original headers and look for spf=pass, dkim=pass, dmarc=pass. JustEmails auto-configures all three plus MTA-STS when you add a domain, so this usually means DNS hasn't propagated or a record got overwritten elsewhere in your zone — and in my experience it's almost always the second one, because someone added a second SPF record instead of merging into the existing one. Our walkthrough of moving DMARC from p=none to p=reject goes through reading those headers properly.

Connection times out

Port 587 blocked outbound. Test from the controller, not an agent: nc -zv smtp.justemails.app 587.

Advanced: Pin It in Configuration as Code

Running JCasC? Both Jenkins SMTP blocks live under unclassified:

unclassified:
  mailer:
    smtpHost: "smtp.justemails.app"
    smtpPort: "587"
    useSsl: false
    useTls: true
    charset: "UTF-8"
    defaultSuffix: "@yourdomain.com"
  extendedEmailPublisher:
    smtpServer: "smtp.justemails.app"
    smtpPort: "587"
    useTls: true
    credentialsId: "justemails-smtp"
    defaultReplyTo: "build-alerts@yourdomain.com"
    defaultSuffix: "@yourdomain.com"
    defaultContentType: "text/plain"

Fair warning — these key names shift between plugin versions, and the JCasC docs lag the plugins by a release or two. Hit /manage/configuration-as-code/reference on your own controller and confirm the schema before trusting the block above. It's the difference between a clean restart and a controller that boots with mail silently unconfigured.

Next Steps

  • Add a chat fallback. Email for the durable record, Slack or Discord for immediacy. The post block takes both.
  • Route by ownership. One firehose alias gets muted by week three. I've watched it happen on three different teams and the mute is always silent, always permanent, and always discovered during an incident — so give each pipeline its own to and accept the extra config.
  • Watch deliverability. Google Postmaster Tools shows your domain's reputation before your team notices the silence.
  • Page a human for the ones that can't wait. Email is a poor pager. When a red build blocks a release, put a phone call on the end of the escalation chain — VeloCalls handles the call-out leg.
  • Zoom out. If Jenkins is one piece of a larger delivery workflow, DevOS handles agent-driven CI/CD orchestration across tools. Both it and JustEmails come out of Velocity Digital Labs.
  • Track the signal. Failure frequency is real engineering data — JustAnalytics is where we push build and uptime trends.

Frequently Asked Questions

Why does Jenkins have two separate email configurations?

They come from two different plugins. The built-in E-mail Notification block belongs to the Mailer plugin, which ships with most Jenkins installs and powers the basic post-build mail step. Extended E-mail Notification belongs to the Email Extension plugin, which adds templates, triggers, attached logs, and recipient providers. They sit on the same Manage Jenkins page but share no settings whatsoever — filling in one leaves the other completely blank.

How do I test Jenkins SMTP settings without running a build?

In Manage Jenkins → System, open the E-mail Notification section, click Advanced, and tick "Test configuration by sending test e-mail". Enter a recipient address and click the Test configuration button. Jenkins attempts a real SMTP send right there and prints either "Email was successfully sent" or the raw exception. Extended E-mail Notification has its own equivalent test field further down the page — run both, because passing one tells you nothing about the other.

Why do my Jenkins build emails go to spam?

Almost always the From domain isn't authenticated. Jenkins sends from whatever is in the System Admin e-mail address field, and if that domain has no SPF record covering your SMTP provider and no DKIM signing, receivers treat it as unverified mail from an unfamiliar server. Set the From address to a domain you control, confirm SPF, DKIM, and DMARC are live, then check the message headers of a test send for three PASS results.

Should I use the Mailer plugin or the Email Extension plugin?

Use Email Extension for anything you actually care about — it gives you per-trigger recipients, attached build logs, HTML templates, and a proper replyTo parameter. Still configure the Mailer block though, because other plugins borrow its SMTP settings for their own notifications and will fail quietly if it's empty. Configure both, send real notifications through emailext.


Try JustEmails

Unlimited custom domain email hosting for $49/year flat — unlimited domains, unlimited mailboxes, 10 GB storage, full IMAP/SMTP. Built for agencies, freelancers, and anyone managing email across more than one domain.

Start your 7-day free trial → · How it compares

jenkins-smtpbuild-notificationsemail-extension-pluginci-cd-alertsdevops-emailbuildinpublicsaasstudioaiworkforcebuildwithclaude

Related posts

Tutorials
Zabbix and Netdata Alert Delivery Using JustEmails SMTP
12 min read
Tutorials
Nextcloud SMTP Settings: Step-by-Step JustEmails Setup
13 min read
Tutorials
Discourse SMTP Setup: 6 Steps to Outbound and Reply-by-Email
12 min read