/** Non-exception-aware version of the above. */ protected Status trySendRetentionEmail(int memberId, Date secondEmailCutoff, NewStuff filler) { SpamRecord spamRec = _spamRepo.loadSpamRecord(memberId); Date last = spamRec == null ? null : spamRec.retentionSent; Status status = last == null ? null : Status.lookup(spamRec.retentionStatus); if (last != null && last.after(secondEmailCutoff) && status != null && status.success) { // spammed recently, skip return Status.TOO_RECENTLY_SPAMMED; } // load the member MemberRecord mrec = _memberRepo.loadMember(memberId); if (mrec == null) { log.warning("Member deleted during retention mailing?", "memberId", memberId); return Status.MEMBER_DELETED; } // skip placeholder addresses if (MemberMailUtil.isPlaceholderAddress(mrec.accountName)) { return Status.PLACEHOLDER_ADDRESS; } // skip invalid addresses if (!MailUtil.isValidAddress(mrec.accountName)) { return Status.INVALID_ADDRESS; } // oh look, they've logged in! maybe the email(s) worked. clear counter boolean persuaded = (last != null) && mrec.lastSession.after(last); if (persuaded) { spamRec.retentionCountSinceLogin = 0; // fall through, we'll send a mail and save the record below } else if (status == Status.NOT_ENOUGH_FRIENDS || status == Status.NOT_ENOUGH_NEWS) { // reset legacy failures, we now send filler for these people spamRec.retentionCountSinceLogin = 0; // fall through, we'll send a mail and save the record below } else if (spamRec != null && spamRec.retentionCountSinceLogin >= 2) { // they are never coming back... oh well, there are plenty of other fish in the sea return Status.LOST_CAUSE; } // sending the email could take a while so update the spam record here to reduce window // where other peers may conflict with us. NOTE: we do plan to run this job on multiple // servers some day _spamRepo.noteRetentionEmailSending(memberId, spamRec); // choose a successful result based on previous attempts status = Status.SENT_DORMANT; if (persuaded) { status = Status.SENT_PERSUADED; } else if (spamRec == null || spamRec.retentionCount == 0) { status = Status.SENT_LAPSED; } // now send the email MailContent content = sendRetentionEmail(mrec, null, filler, true); // NOTE: this is sort of redundant but increases the integrity of the spam record and // reduces chance of a user getting two emails when we are 1M strong _spamRepo.noteRetentionEmailResult(memberId, status.value); // log an event for successes. the result is the lapse status if (status.success) { _eventLog.retentionMailSent( mrec.memberId, mrec.visitorId, status.name(), content.subjectLine, content.bucket.name, content.numFriends, content.numPersonalMessages, mrec.isValidated()); } return status; }