Sentry fix: Additional rare null-scenario handling

This commit is contained in:
Ben Gotow 2019-06-16 15:22:22 -05:00
parent c50cfaf3ff
commit f1bdd892ed
5 changed files with 24 additions and 27 deletions

View file

@ -86,14 +86,14 @@ export async function expandAccountWithCommonSettings(account: Account) {
const imap = (template.servers.imap || [])[0] || ({} as any); const imap = (template.servers.imap || [])[0] || ({} as any);
const smtp = (template.servers.smtp || [])[0] || ({} as any); const smtp = (template.servers.smtp || [])[0] || ({} as any);
const defaults = { const defaults = {
imap_host: imap.hostname.replace('{domain}', domain), imap_host: (imap.hostname || '').replace('{domain}', domain),
imap_port: imap.port, imap_port: imap.port,
imap_username: usernameWithFormat('email'), imap_username: usernameWithFormat('email'),
imap_password: populated.settings.imap_password, imap_password: populated.settings.imap_password,
imap_security: imap.starttls ? 'STARTTLS' : imap.ssl ? 'SSL / TLS' : 'none', imap_security: imap.starttls ? 'STARTTLS' : imap.ssl ? 'SSL / TLS' : 'none',
imap_allow_insecure_ssl: false, imap_allow_insecure_ssl: false,
smtp_host: smtp.hostname.replace('{domain}', domain), smtp_host: (smtp.hostname || '').replace('{domain}', domain),
smtp_port: smtp.port, smtp_port: smtp.port,
smtp_username: usernameWithFormat('email'), smtp_username: usernameWithFormat('email'),
smtp_password: populated.settings.smtp_password || populated.settings.imap_password, smtp_password: populated.settings.smtp_password || populated.settings.imap_password,

View file

@ -63,7 +63,7 @@ export default class ThreadListContextMenu {
} }
findWithFrom(): TemplateItem | null { findWithFrom(): TemplateItem | null {
if (this.threadIds.length !== 1) { if (this.threadIds.length !== 1 || !this.threads[0]) {
return null; return null;
} }
const first = this.threads[0]; const first = this.threads[0];
@ -78,7 +78,7 @@ export default class ThreadListContextMenu {
} }
findWithSubject(): TemplateItem | null { findWithSubject(): TemplateItem | null {
if (this.threadIds.length !== 1) { if (this.threadIds.length !== 1 || !this.threads[0]) {
return null; return null;
} }
const subject = this.threads[0].subject; const subject = this.threads[0].subject;
@ -95,7 +95,7 @@ export default class ThreadListContextMenu {
} }
replyItem(): TemplateItem | null { replyItem(): TemplateItem | null {
if (this.threadIds.length !== 1) { if (this.threadIds.length !== 1 || !this.threads[0]) {
return null; return null;
} }
return { return {
@ -112,7 +112,7 @@ export default class ThreadListContextMenu {
} }
replyAllItem(): Promise<TemplateItem> | null { replyAllItem(): Promise<TemplateItem> | null {
if (this.threadIds.length !== 1) { if (this.threadIds.length !== 1 || !this.threads[0]) {
return null; return null;
} }
@ -138,7 +138,7 @@ export default class ThreadListContextMenu {
} }
forwardItem(): TemplateItem | null { forwardItem(): TemplateItem | null {
if (this.threadIds.length !== 1) { if (this.threadIds.length !== 1 || !this.threads[0]) {
return null; return null;
} }
return { return {
@ -246,7 +246,7 @@ export default class ThreadListContextMenu {
} }
createMailboxLinkItem() { createMailboxLinkItem() {
if (this.threadIds.length !== 1) { if (this.threadIds.length !== 1 || !this.threads[0]) {
return null; return null;
} }

View file

@ -351,8 +351,8 @@ class DatabaseStore extends MailspringStore {
if (!this._agent) { if (!this._agent) {
this._agentOpenQueries = {}; this._agentOpenQueries = {};
this._agent = childProcess.fork(AGENT_PATH, [], { silent: true }); this._agent = childProcess.fork(AGENT_PATH, [], { silent: true });
this._agent.stdout.on('data', data => console.log(data.toString())); if (this._agent.stdout) this._agent.stdout.on('data', data => console.log(data.toString()));
this._agent.stderr.on('data', data => console.error(data.toString())); if (this._agent.stderr) this._agent.stderr.on('data', data => console.error(data.toString()));
this._agent.on('close', code => { this._agent.on('close', code => {
debug(`Query Agent: exited with code ${code}`); debug(`Query Agent: exited with code ${code}`);
this._agent = null; this._agent = null;

View file

@ -18,7 +18,8 @@ import { Thread } from '../models/Thread';
let DraftStore: typeof import('./draft-store').default = null; let DraftStore: typeof import('./draft-store').default = null;
type ReplyType = 'reply' | 'reply-all' export type ReplyType = 'reply' | 'reply-all';
export type ReplyBehavior = 'prefer-existing' | 'prefer-existing-if-pristine';
async function prepareBodyForQuoting(body) { async function prepareBodyForQuoting(body) {
// TODO: Fix inline images // TODO: Fix inline images
@ -40,8 +41,10 @@ class DraftFactory {
// Having a consistent accountID prefix is what allows us to ensure that you // Having a consistent accountID prefix is what allows us to ensure that you
// don't trigger your own open-tracked emails, for example. [BG NOTE "HMID"] // don't trigger your own open-tracked emails, for example. [BG NOTE "HMID"]
// //
const auuid = uuidv4().toUpperCase().split('-') const auuid = uuidv4()
auuid.splice(0, 1, account.id.toUpperCase()) .toUpperCase()
.split('-');
auuid.splice(0, 1, account.id.toUpperCase());
const defaults = { const defaults = {
body: '<br/>', body: '<br/>',
@ -154,7 +157,7 @@ class DraftFactory {
message: Message; message: Message;
thread: Thread; thread: Thread;
type: ReplyType; type: ReplyType;
behavior: string; behavior: ReplyBehavior;
}) { }) {
if (!['reply', 'reply-all'].includes(type)) { if (!['reply', 'reply-all'].includes(type)) {
throw new Error(`createOrUpdateDraftForReply called with ${type}, not reply or reply-all`); throw new Error(`createOrUpdateDraftForReply called with ${type}, not reply or reply-all`);
@ -262,7 +265,7 @@ class DraftFactory {
}); });
} }
async candidateDraftForUpdating(message, behavior) { async candidateDraftForUpdating(message: Message, behavior: ReplyBehavior) {
if (!['prefer-existing-if-pristine', 'prefer-existing'].includes(behavior)) { if (!['prefer-existing-if-pristine', 'prefer-existing'].includes(behavior)) {
return null; return null;
} }
@ -279,7 +282,6 @@ class DraftFactory {
if (candidateDrafts.length === 0) { if (candidateDrafts.length === 0) {
return null; return null;
} }
if (behavior === 'prefer-existing') { if (behavior === 'prefer-existing') {
return candidateDrafts.pop(); return candidateDrafts.pop();
} }
@ -290,21 +292,16 @@ class DraftFactory {
DraftStore.sessionForClientId(candidateDraft.headerMessageId) DraftStore.sessionForClientId(candidateDraft.headerMessageId)
) )
); );
for (const session of sessions) { return sessions.map(s => s.draft()).find(d => d && d.pristine);
if (session.draft().pristine) {
return session.draft();
}
}
return null;
} }
} }
updateDraftForReply(draft: Message, { type, message }: {type: ReplyType, message: Message}) { updateDraftForReply(draft: Message, { type, message }: { type: ReplyType; message: Message }) {
if (!(message && draft)) { if (!(message && draft)) {
throw new Error('updateDraftForReply: Expected message and existing draft.'); throw new Error('updateDraftForReply: Expected message and existing draft.');
} }
const updated: {to: Contact[], cc: Contact[]} = { to: [...draft.to], cc: [...draft.cc] }; const updated: { to: Contact[]; cc: Contact[] } = { to: [...draft.to], cc: [...draft.cc] };
const replySet = message.participantsForReply(); const replySet = message.participantsForReply();
const replyAllSet = message.participantsForReplyAll(); const replyAllSet = message.participantsForReplyAll();
let targetSet = null; let targetSet = null;

View file

@ -1,7 +1,7 @@
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
import MailspringStore from 'mailspring-store'; import MailspringStore from 'mailspring-store';
import { DraftEditingSession } from './draft-editing-session'; import { DraftEditingSession } from './draft-editing-session';
import DraftFactory from './draft-factory'; import DraftFactory, { ReplyType, ReplyBehavior } from './draft-factory';
import DatabaseStore from './database-store'; import DatabaseStore from './database-store';
import { SendActionsStore } from './send-actions-store'; import { SendActionsStore } from './send-actions-store';
import FocusedContentStore from './focused-content-store'; import FocusedContentStore from './focused-content-store';
@ -223,8 +223,8 @@ class DraftStore extends MailspringStore {
behavior, behavior,
}: IThreadMessageModelOrId & { }: IThreadMessageModelOrId & {
popout?: boolean; popout?: boolean;
type: 'reply' | 'reply-all'; type: ReplyType;
behavior: string; behavior: ReplyBehavior;
}) => { }) => {
return Promise.props(this._modelifyContext({ thread, threadId, message, messageId })) return Promise.props(this._modelifyContext({ thread, threadId, message, messageId }))
.then(({ message: m, thread: t }) => { .then(({ message: m, thread: t }) => {