I believe I've gotten to the bottom of this. I'm not sure what the exact right fix is, because it seems there might be several. Bear with me, this might take a while:
We use job-dsl-plugin to configure our jobs. And when I added a secondFailure trigger via job-dsl-plugin, that's when I observed the behavior I described. If I then re-saved the job in the Jenkins UI, the problem went away. This led me to investigate the difference in config.xml between the job-dsl generated version and the JenkinsUI generated version, and it was this:
in the job-dsl generated job, I saw: "<failureCount>0</failureCount>" for the SecondFailureTrigger element.
But in the Jenkins UI generated job, I saw "<failureCount>2</failureCount>" for the SecondFailureTrigger element.
I then added some debugging to the email-ext and uploaded, and saw that in https://github.com/jenkinsci/email-ext-plugin/blob/master/src/main/java/hudson/plugins/emailext/plugins/trigger/NthFailureTrigger.java#L35-L53, because failureCount was 0, then that entire loop was skipped, and it'd hit the last line:
return run == null || run.getResult() == Result.SUCCESS || run.getResult() == Result.UNSTABLE;
And since the result was SUCCESS, it'd return true, and the email would get triggered.
So there are 2 problems:
1) for some reason, the job-dsl version generates a failureCount of 0, which causes the for loop to get skipped
2) the return seems, to me, to have incorrect logic. I can't figure out why it'd return true if the result was SUCCESS.
So to fix this, I noticed that FirstFailureTrigger has a readResolve() block that seems to cover this exact condition. Thus, I added a readResolve() block to SecondFailureTrigger, just replacing "1" with "2"
Re-uploaded the plugin, and that fixed everything.
So to me, that seems like a sensible fix and I'm happy to submit a PR if you think that's correct.
Still, though, that return in trigger() seems off to me, so you probably want to check that out. If you think the logic should be Result.FAILURE instead of Result.SUCCESS, let me know and I can add that to the PR