Blog from December, 2019

This page constitutes random notes from my work day as an Atlassian product consultant, put up in the vague hope they might benefit others. Expect rambling, reference to unsolved problems, and plenty of stacktraces. Check the date as any information given is likely to be stale.

Today's project: create a Confluence report that shows hours logged for all users in a given month. Let the user specify the year/month in question, and optionally filter the set of reported users:

This report shows hours for all  users even if they haven't logged any this month, which is something Tempo's reports can't do.

Implementation

I have expanded on the implementation in a KB article, Creating interactive Jira reports in Confluence using free tools

This page constitutes random notes from my work day as an Atlassian product consultant, put up in the vague hope they might benefit others. Expect rambling, reference to unsolved problems, and plenty of stacktraces. Check the date as any information given is likely to be stale.

Just a notice that I will be gradually moving my open source repositories from Bitbucket (http://bitbucket.org/redradish) to Github (https://github.com/redradishtech).

Github has always been faster and nicer, with better network effects. I've stuck with Bitbucket until now for its Mercurial support. With the abrupt termination of Mercurial support I have no further reason to stay. My non-public code will live https://meta.sr.ht/

This page constitutes random notes from my work day as an Atlassian product consultant, put up in the vague hope they might benefit others. Expect rambling, reference to unsolved problems, and plenty of stacktraces. Check the date as any information given is likely to be stale.

Sending email via Postfix

I generally like to configure Jira and Confluence to send outgoing emails to localhost , and there have Postfix do the final mail delivery:

Delegating to Postfix has at least three benefits:

  • It keeps sensitive SMTP credentials out of Jira
  • I can configure Postfix on staging to 'blackhole' all outgoing emails (i.e. send them to a local file), so when production Jira data is run on staging, there's no chance of staging accidentally emailing people even if I forgot to set -Datlassian.mail.senddisabled=true 
  • It gets emails out of Jira's "useless" (to quote Jira's tech lead) mail queue as fast as possible, into a competently designed MTA that actually persists emails across restarts and handles retries to overcome transient errors.

Postfix's message size limit

One caveat I discovered today: Postfix will reject emails larger than a certain size (the message_size_limit parameter), including emails from Jira. If you have JETI installed, and users use JETI to email issues with their attachments, then it's quite easy for Jira to be sending JETI emails over 10Mb. Postfix rejects them, and they end up in the Jira error queue, where they languish forever until Jira is restarted, whereupon they are lost (did I mention "useless"?).

So if you don't want to lose your outgoing JETI emails, increase Postfix's message_size_limit  to whatever you're comfortable sending. In /etc/postfix/main.cf:

# Increase the maximum email size from 10Mb to 50Mb. https://www.redradishtech.com/x/JoAjAQ
message_size_limit = 50240000

Then sudo postfix reload

SMTP timeouts


Following increasing the message_size_limit , I noticed a SocketTimeoutExceptions in your atlassian-jira-outgoing-mail.log:

2019-12-17 22:11:08,828 ERROR [] Sending mailitem To='user@example.com' Subject='Issue Updated: (IT-183421) Sample ticket' From='null' FromName='Jeff Turner (Jira)' Cc='' Bcc='' ReplyTo='null' InReplyTo='<JIRA.502599.1572547564000@Atlassian.JIRA>' MimeType='text/html' Encoding='UTF-8' Multipart='javax.mail.internet.MimeMultipart@3fb8818d' MessageId='JIRA.502599.1572547564000.10326.1576446859026@Atlassian.JIRA' ExcludeSubjectPrefix=false' jeff@redradishtech.com 1330x2600246x1 svwdbg 63.80.172.147 /secure/admin/MailQueueAdmin.jspa Error occurred in sending e-mail: To='user@example.com' Subject='Issue Updated: (IT-183421) Sample ticket' From='null' FromName='Jeff Turner (Jira)' Cc='' Bcc='' ReplyTo='null' InReplyTo='<JIRA.502599.1572547564000@Atlassian.JIRA>' MimeType='text/html' Encoding='UTF-8' Multipart='javax.mail.internet.MimeMultipart@3fb8818d' MessageId='JIRA.502599.1572547564000.10326.1576446859026@Atlassian.JIRA' ExcludeSubjectPrefix=false'
com.atlassian.mail.MailException: javax.mail.MessagingException: Exception reading response;
      nested exception is:
        java.net.SocketTimeoutException: Read timed out
        at com.atlassian.mail.server.impl.SMTPMailServerImpl.sendWithMessageId(SMTPMailServerImpl.java:222) [atlassian-mail-5.0.0.jar:?]
        at com.atlassian.mail.queue.SingleMailQueueItem.send(SingleMailQueueItem.java:44) [atlassian-mail-5.0.0.jar:?]
...
Caused by: javax.mail.MessagingException: Exception reading response;
      nested exception is:
        java.net.SocketTimeoutException: Read timed out
        at com.sun.mail.smtp.SMTPTransport.readServerResponse(SMTPTransport.java:2445) [javax.mail-1.6.0.jar:1.6.0]
        at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:2322) [javax.mail-1.6.0.jar:1.6.0]
        at com.sun.mail.smtp.SMTPTransport.finishData(SMTPTransport.java:2095) [javax.mail-1.6.0.jar:1.6.0]
        at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1301) [javax.mail-1.6.0.jar:1.6.0]
        at com.atlassian.mail.server.impl.SMTPMailServerImpl.sendMimeMessage(SMTPMailServerImpl.java:242) [atlassian-mail-5.0.0.jar:?]
        at com.atlassian.mail.server.managers.EventAwareSMTPMailServer.sendMimeMessage(EventAwareSMTPMailServer.java:25) [classes/:?]
        at com.atlassian.mail.server.impl.SMTPMailServerImpl.sendWithMessageId(SMTPMailServerImpl.java:184) [atlassian-mail-5.0.0.jar:?]
        ... 297 more
Caused by: java.net.SocketTimeoutException: Read timed out
        at java.base/java.net.SocketInputStream.socketRead0(Native Method) [?:?]
        at java.base/java.net.SocketInputStream.socketRead(SocketInputStream.java:115) [?:?]
        at java.base/java.net.SocketInputStream.read(SocketInputStream.java:168) [?:?]
        at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140) [?:?]
        at com.sun.mail.util.TraceInputStream.read(TraceInputStream.java:126) [javax.mail-1.6.0.jar:1.6.0]
        at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:252) [?:?]
        at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:271) [?:?]
        at com.sun.mail.util.LineInputStream.readLine(LineInputStream.java:104) [javax.mail-1.6.0.jar:1.6.0]
        at com.sun.mail.smtp.SMTPTransport.readServerResponse(SMTPTransport.java:2425) [javax.mail-1.6.0.jar:1.6.0]
        ... 303 more

The notification in the error queue was still there, but Postfix indicated that it had received and forwarded on the email!

Jira has a Timeout  setting for SMTP servers in the Outgoing Mail  section, and the default value is 10 seconds. From the stacktrace, it appears Jira opened a SMTP connection to Postgres, sent the large email (in my case, 23Mb), and then timed out waiting for a response from Postgres. Postgres considered the delivery a success, while Jira considered it a failure, and left the email in the error queue. Clicking 'Resend error queue' results in the same email being sent again.

The fix for this is to increase Jira's SMTP timeout, which can be done in the SMTP Mail Server settings under Outgoing Mail. On the principle of avoiding Jira's error queue at all costs, this timeout should be set to something large - anything less than 1 minute, which is the queue flush frequency:

The Confluence Numbered Headings plugin is one of those plugins that was free for many years, then went commercial.

Until recently it still worked, but not any more. As of Confluence 7.1 and later the UPM flags the old version as incompatible:

The effect of this incompatibility is subtle: Numbered Headings works fine just as before, but now if you try to insert any macro that has a body using '+' icon, you get an endless spinner, and a Javascript AJS.clone is not a function  error:


The good news is that after upgrading, the plugin is still free: it just as a 'Pro' version:

So upgrade away, and if your budget permits, support the plugin authors by paying for the Pro version.