2019-09-13 13:49:11 +02:00
import o from "ospec"
2022-01-07 15:58:30 +01:00
// @ts-ignore[untyped-import]
2020-09-18 14:41:31 +02:00
import en from "../../../src/translations/en"
import type { IUserController } from "../../../src/api/main/UserController"
import type { LoginController } from "../../../src/api/main/LoginController"
2022-03-11 13:12:32 +01:00
import { MailModel } from "../../../src/mail/model/MailModel"
2022-02-03 14:55:40 +01:00
import { Contact , ContactTypeRef , createContact } from "../../../src/api/entities/tutanota/Contact"
import { ContactModel } from "../../../src/contacts/model/ContactModel"
2022-03-11 13:12:32 +01:00
import { assertThrows , verify } from "@tutao/tutanota-test-utils"
2022-02-03 14:55:40 +01:00
import { downcast , isSameTypeRef } from "@tutao/tutanota-utils"
2020-09-18 14:41:31 +02:00
import { createTutanotaProperties } from "../../../src/api/entities/tutanota/TutanotaProperties"
2021-02-03 17:13:38 +01:00
import { SendMailModel , TOO_MANY_VISIBLE_RECIPIENTS } from "../../../src/mail/editor/SendMailModel"
2020-09-18 14:41:31 +02:00
import { createGroupInfo } from "../../../src/api/entities/sys/GroupInfo"
import { createMailboxGroupRoot } from "../../../src/api/entities/tutanota/MailboxGroupRoot"
import { createGroup } from "../../../src/api/entities/sys/Group"
import { createMailBox } from "../../../src/api/entities/tutanota/MailBox"
import { ConversationType , GroupType , MailMethod , OperationType } from "../../../src/api/common/TutanotaConstants"
2022-02-03 14:55:40 +01:00
import { lang } from "../../../src/misc/LanguageViewModel"
import { createCustomer , CustomerTypeRef } from "../../../src/api/entities/sys/Customer"
2020-09-18 14:41:31 +02:00
import { createUser , UserTypeRef } from "../../../src/api/entities/sys/User"
2021-04-29 15:09:21 +02:00
import type { RecipientInfo } from "../../../src/api/common/RecipientInfo"
import { isTutanotaMailAddress , RecipientInfoType } from "../../../src/api/common/RecipientInfo"
2020-09-18 14:41:31 +02:00
import { createMail , MailTypeRef } from "../../../src/api/entities/tutanota/Mail"
2022-02-03 14:55:40 +01:00
import { EventController } from "../../../src/api/main/EventController"
2020-09-18 14:41:31 +02:00
import { createMailAddress } from "../../../src/api/entities/tutanota/MailAddress"
import { createGroupMembership } from "../../../src/api/entities/sys/GroupMembership"
2021-02-03 17:13:38 +01:00
import { UserError } from "../../../src/api/main/UserError"
2020-09-18 14:41:31 +02:00
import { ContactListTypeRef } from "../../../src/api/entities/tutanota/ContactList"
import { EntityClient } from "../../../src/api/common/EntityClient"
import { CustomerAccountCreateDataTypeRef } from "../../../src/api/entities/tutanota/CustomerAccountCreateData"
import { NotificationMailTypeRef } from "../../../src/api/entities/tutanota/NotificationMail"
import { ChallengeTypeRef } from "../../../src/api/entities/sys/Challenge"
2021-02-03 17:13:38 +01:00
import { getContactDisplayName } from "../../../src/contacts/model/ContactUtils"
2022-02-03 14:55:40 +01:00
import { ConversationEntryTypeRef , createConversationEntry } from "../../../src/api/entities/tutanota/ConversationEntry"
2022-01-07 15:58:30 +01:00
import { isSameId } from "../../../src/api/common/utils/EntityUtils"
2021-08-06 17:44:09 +02:00
import { MailFacade } from "../../../src/api/worker/facades/MailFacade"
2022-01-07 15:58:30 +01:00
import { RecipientField } from "../../../src/mail/model/MailUtils"
2022-03-11 13:12:32 +01:00
import { func , instance , matchers , object , replace , when } from "testdouble"
2022-02-03 14:55:40 +01:00
const { anything , argThat } = matchers
2020-09-18 14:41:31 +02:00
type TestIdGenerator = {
2022-01-07 15:58:30 +01:00
currentIdValue : number ,
currentListIdValue : number ,
newId : ( ) = > Id
newListId : ( ) = > Id
2020-09-18 14:41:31 +02:00
newIdTuple : ( ) = > IdTuple
}
let testIdGenerator : TestIdGenerator
const EXTERNAL_ADDRESS_1 = "address1@test.com"
const EXTERNAL_ADDRESS_2 = "address2@test.com"
const DEFAULT_SENDER_FOR_TESTING = "test@tutanota.de"
const INTERNAL_RECIPIENT_1 = {
name : "test1" ,
address : "test1@tutanota.de" ,
2022-01-07 15:58:30 +01:00
contact : null ,
2020-09-18 14:41:31 +02:00
}
const BODY_TEXT_1 = "lorem ipsum dolor yaddah yaddah"
const SUBJECT_LINE_1 = "Did you get that thing I sent ya"
const STRONG_PASSWORD = "@()IE!)(@FME)0-123jfDSA32SDACmmnvnvddEW"
const WEAK_PASSWORD = "123"
2022-02-03 14:55:40 +01:00
2020-11-03 08:42:25 +01:00
o . spec ( "SendMailModel" , function ( ) {
2022-02-03 14:55:40 +01:00
2020-11-03 08:42:25 +01:00
o . before ( function ( ) {
2020-09-18 14:41:31 +02:00
// we need lang initialized because the SendMailModel constructor requires some translation
lang . init ( en )
} )
2022-02-03 14:55:40 +01:00
let mailModel : MailModel ,
2022-01-07 15:58:30 +01:00
entity : EntityClient ,
2022-02-03 14:55:40 +01:00
mailFacade : MailFacade
let model : SendMailModel
2020-11-03 08:42:25 +01:00
o . beforeEach ( function ( ) {
2021-08-06 17:44:09 +02:00
testIdGenerator = {
currentIdValue : 0 ,
currentListIdValue : 0 ,
2022-01-07 15:58:30 +01:00
2021-08-06 17:44:09 +02:00
newId ( ) : Id {
return ( this . currentIdValue ++ ) . toString ( )
} ,
2022-01-07 15:58:30 +01:00
2021-08-06 17:44:09 +02:00
newListId ( ) : Id {
return ( this . currentListIdValue ++ ) . toString ( )
} ,
2022-01-07 15:58:30 +01:00
2021-08-06 17:44:09 +02:00
newIdTuple ( ) : IdTuple {
return [ this . newListId ( ) , this . newId ( ) ]
2022-01-07 15:58:30 +01:00
} ,
2021-08-06 17:44:09 +02:00
}
2022-02-03 14:55:40 +01:00
entity = instance ( EntityClient )
when ( entity . loadRoot ( argThat ( typeRef = > isSameTypeRef ( typeRef , ContactListTypeRef ) ) , anything ( ) ) )
. thenDo (
( ) = > ( { contacts : testIdGenerator.newId ( ) } )
)
when ( entity . load ( anything ( ) , anything ( ) , anything ( ) ) )
. thenDo ( ( typeRef , id , params ) = > ( { _type : typeRef , _id : id } ) )
mailModel = instance ( MailModel )
const contactModel = object < ContactModel > ( )
when ( contactModel . contactListId ( ) ) . thenResolve ( "contactListId" )
when ( contactModel . searchForContact ( anything ( ) ) ) . thenResolve ( null )
mailFacade = instance ( MailFacade )
when ( mailFacade . createDraft ( anything ( ) ) ) . thenDo ( ( ) = > createMail ( ) )
when ( mailFacade . updateDraft ( anything ( ) ) ) . thenDo ( ( ) = > createMail ( ) )
when ( mailFacade . getRecipientKeyData ( anything ( ) ) ) . thenResolve ( null )
2022-01-07 15:58:30 +01:00
const tutanotaProperties = createTutanotaProperties (
2022-02-03 14:55:40 +01:00
{
2022-01-07 15:58:30 +01:00
defaultSender : DEFAULT_SENDER_FOR_TESTING ,
defaultUnconfidential : true ,
notificationMailLanguage : "en" ,
noAutomaticContacts : false ,
2022-02-03 14:55:40 +01:00
} ,
2022-01-07 15:58:30 +01:00
)
2022-02-03 14:55:40 +01:00
const user = createUser ( {
2022-01-07 15:58:30 +01:00
userGroup : createGroupMembership ( {
_id : testIdGenerator.newId ( ) ,
group : testIdGenerator.newId ( ) ,
} ) ,
2020-09-18 14:41:31 +02:00
memberships : [
2022-01-07 15:58:30 +01:00
createGroupMembership ( {
_id : testIdGenerator.newId ( ) ,
groupType : GroupType.Contact ,
} ) ,
] ,
2020-09-18 14:41:31 +02:00
} )
2022-02-03 14:55:40 +01:00
const userController = object < IUserController > ( )
replace ( userController , "user" , user )
replace ( userController , "props" , tutanotaProperties )
when ( userController . loadCustomer ( ) ) . thenResolve ( createCustomer ( ) )
const loginController = object < LoginController > ( )
when ( loginController . isInternalUserLoggedIn ( ) ) . thenReturn ( true )
when ( loginController . getUserController ( ) ) . thenReturn ( userController )
const eventController = instance ( EventController )
const mailboxDetails = {
2020-09-18 14:41:31 +02:00
mailbox : createMailBox ( ) ,
folders : [ ] ,
mailGroupInfo : createGroupInfo ( ) ,
mailGroup : createGroup ( ) ,
2022-01-07 15:58:30 +01:00
mailboxGroupRoot : createMailboxGroupRoot ( ) ,
2020-09-18 14:41:31 +02:00
}
2022-02-03 14:55:40 +01:00
2022-01-07 15:58:30 +01:00
model = new SendMailModel (
mailFacade ,
2022-02-03 14:55:40 +01:00
loginController ,
2022-01-07 15:58:30 +01:00
mailModel ,
contactModel ,
2022-02-03 14:55:40 +01:00
eventController ,
2022-01-07 15:58:30 +01:00
entity ,
mailboxDetails ,
)
2022-02-03 14:55:40 +01:00
replace ( model , "_getDefaultSender" , ( ) = > DEFAULT_SENDER_FOR_TESTING )
2020-09-18 14:41:31 +02:00
} )
2022-02-03 14:55:40 +01:00
2020-11-03 08:42:25 +01:00
o . spec ( "initialization" , function ( ) {
o . beforeEach ( function ( ) {
2022-02-03 14:55:40 +01:00
replace ( model , "_createAndResolveRecipientInfo" , ( name , address , contact , resolveLazily ) = > {
2020-10-22 14:55:01 +02:00
const ri : RecipientInfo = {
2020-09-18 14:41:31 +02:00
type : isTutanotaMailAddress ( address ) ? RecipientInfoType.INTERNAL : RecipientInfoType.EXTERNAL ,
mailAddress : address ,
name : name ,
2022-01-07 15:58:30 +01:00
contact :
contact ||
createContact ( {
firstName : name ,
mailAddresses : [ address ] ,
} ) ,
resolveContactPromise : null ,
2020-09-18 14:41:31 +02:00
}
2020-10-22 14:55:01 +02:00
return [ ri , Promise . resolve ( ri ) ]
2020-09-18 14:41:31 +02:00
} )
} )
2020-11-03 08:42:25 +01:00
o ( "initWithTemplate empty" , async function ( ) {
2020-10-22 14:55:01 +02:00
await model . initWithTemplate ( { } , "" , "" , [ ] , false )
2020-09-18 14:41:31 +02:00
o ( model . getConversationType ( ) ) . equals ( ConversationType . NEW )
o ( model . getSubject ( ) ) . equals ( "" )
o ( model . getBody ( ) ) . equals ( "" )
o ( model . getDraft ( ) ) . equals ( null )
o ( model . allRecipients ( ) . length ) . equals ( 0 )
o ( model . getSender ( ) ) . equals ( DEFAULT_SENDER_FOR_TESTING )
o ( model . isConfidential ( ) ) . equals ( true )
o ( model . containsExternalRecipients ( ) ) . equals ( false )
o ( model . getAttachments ( ) . length ) . equals ( 0 )
o ( model . hasMailChanged ( ) ) . equals ( false ) ( "initialization should not flag mail changed" )
} )
2020-11-03 08:42:25 +01:00
o ( "initWithTemplate data" , async function ( ) {
2020-09-18 14:41:31 +02:00
const initializedModel = await model . initWithTemplate (
2022-01-07 15:58:30 +01:00
{
to : [ INTERNAL_RECIPIENT_1 ] ,
} ,
2020-09-18 14:41:31 +02:00
SUBJECT_LINE_1 ,
BODY_TEXT_1 ,
[ ] ,
false ,
2022-01-07 15:58:30 +01:00
DEFAULT_SENDER_FOR_TESTING ,
2020-09-18 14:41:31 +02:00
)
o ( initializedModel . getConversationType ( ) ) . equals ( ConversationType . NEW )
o ( initializedModel . getSubject ( ) ) . equals ( SUBJECT_LINE_1 )
o ( initializedModel . getBody ( ) ) . equals ( BODY_TEXT_1 )
o ( initializedModel . getDraft ( ) ) . equals ( null )
o ( initializedModel . allRecipients ( ) . length ) . equals ( 1 )
o ( initializedModel . getSender ( ) ) . equals ( DEFAULT_SENDER_FOR_TESTING )
o ( model . isConfidential ( ) ) . equals ( true )
o ( model . containsExternalRecipients ( ) ) . equals ( false )
o ( initializedModel . getAttachments ( ) . length ) . equals ( 0 )
o ( initializedModel . hasMailChanged ( ) ) . equals ( false ) ( "initialization should not flag mail changed" )
} )
2020-11-03 08:42:25 +01:00
o ( "initWithTemplate duplicated recipients" , async function ( ) {
2020-09-18 14:41:31 +02:00
const duplicate = {
name : INTERNAL_RECIPIENT_1.name ,
address : INTERNAL_RECIPIENT_1.address ,
2022-01-07 15:58:30 +01:00
contact : INTERNAL_RECIPIENT_1.contact ,
2020-09-18 14:41:31 +02:00
}
const initializedModel = await model . initWithTemplate (
2022-01-07 15:58:30 +01:00
{
to : [ INTERNAL_RECIPIENT_1 , duplicate ] ,
} ,
2020-09-18 14:41:31 +02:00
SUBJECT_LINE_1 ,
BODY_TEXT_1 ,
[ ] ,
false ,
2022-01-07 15:58:30 +01:00
DEFAULT_SENDER_FOR_TESTING ,
2020-09-18 14:41:31 +02:00
)
o ( initializedModel . getConversationType ( ) ) . equals ( ConversationType . NEW )
o ( initializedModel . getSubject ( ) ) . equals ( SUBJECT_LINE_1 )
o ( initializedModel . getBody ( ) ) . equals ( BODY_TEXT_1 )
o ( initializedModel . getDraft ( ) ) . equals ( null )
o ( initializedModel . allRecipients ( ) . length ) . equals ( 1 )
o ( initializedModel . getSender ( ) ) . equals ( DEFAULT_SENDER_FOR_TESTING )
o ( model . isConfidential ( ) ) . equals ( true )
o ( model . containsExternalRecipients ( ) ) . equals ( false )
o ( initializedModel . getAttachments ( ) . length ) . equals ( 0 )
o ( initializedModel . hasMailChanged ( ) ) . equals ( false ) ( "initialization should not flag mail changed" )
} )
2020-11-03 08:42:25 +01:00
o ( "initWithDraft with blank data" , async function ( ) {
2020-09-18 14:41:31 +02:00
const draftMail = createMail ( {
confidential : false ,
sender : createMailAddress ( ) ,
toRecipients : [ ] ,
ccRecipients : [ ] ,
bccRecipients : [ ] ,
subject : "" ,
2022-01-07 15:58:30 +01:00
replyTos : [ ] ,
2022-02-03 14:55:40 +01:00
conversationEntry : testIdGenerator.newIdTuple ( )
2020-09-18 14:41:31 +02:00
} )
2022-02-03 14:55:40 +01:00
when ( entity . load ( ConversationEntryTypeRef , draftMail . conversationEntry ) ) . thenResolve ( createConversationEntry ( { conversationType : ConversationType.REPLY } ) )
2021-07-02 14:34:05 +02:00
const initializedModel = await model . initWithDraft ( draftMail , [ ] , BODY_TEXT_1 , Promise . resolve ( new Map ( ) ) )
2020-11-03 08:42:25 +01:00
o ( initializedModel . getConversationType ( ) ) . equals ( ConversationType . REPLY )
2020-09-18 14:41:31 +02:00
o ( initializedModel . getSubject ( ) ) . equals ( draftMail . subject )
o ( initializedModel . getBody ( ) ) . equals ( BODY_TEXT_1 )
o ( initializedModel . getDraft ( ) ) . equals ( draftMail )
o ( initializedModel . allRecipients ( ) . length ) . equals ( 0 )
o ( initializedModel . getSender ( ) ) . equals ( DEFAULT_SENDER_FOR_TESTING )
o ( model . isConfidential ( ) ) . equals ( true )
o ( model . containsExternalRecipients ( ) ) . equals ( false )
o ( initializedModel . getAttachments ( ) . length ) . equals ( 0 )
o ( initializedModel . hasMailChanged ( ) ) . equals ( false ) ( "initialization should not flag mail changed" )
} )
2020-11-03 08:42:25 +01:00
o ( "initWithDraft with some data" , async function ( ) {
2020-09-18 14:41:31 +02:00
const draftMail = createMail ( {
confidential : true ,
sender : createMailAddress ( ) ,
2022-01-07 15:58:30 +01:00
toRecipients : [
createMailAddress ( {
address : "" ,
} ) ,
createMailAddress ( {
address : EXTERNAL_ADDRESS_1 ,
} ) ,
] ,
ccRecipients : [
createMailAddress ( {
address : EXTERNAL_ADDRESS_2 ,
} ) ,
] ,
2020-09-18 14:41:31 +02:00
bccRecipients : [ ] ,
subject : SUBJECT_LINE_1 ,
2022-01-07 15:58:30 +01:00
replyTos : [ ] ,
2022-02-03 14:55:40 +01:00
conversationEntry : testIdGenerator.newIdTuple ( )
2020-09-18 14:41:31 +02:00
} )
2022-02-03 14:55:40 +01:00
when ( entity . load ( ConversationEntryTypeRef , draftMail . conversationEntry ) )
. thenResolve ( createConversationEntry ( { conversationType : ConversationType.FORWARD } ) )
2021-07-02 14:34:05 +02:00
const initializedModel = await model . initWithDraft ( draftMail , [ ] , BODY_TEXT_1 , Promise . resolve ( new Map ( ) ) )
2020-11-03 08:42:25 +01:00
o ( initializedModel . getConversationType ( ) ) . equals ( ConversationType . FORWARD )
2020-09-18 14:41:31 +02:00
o ( initializedModel . getSubject ( ) ) . equals ( draftMail . subject )
o ( initializedModel . getBody ( ) ) . equals ( BODY_TEXT_1 )
o ( initializedModel . getDraft ( ) ) . equals ( draftMail )
2022-01-07 15:58:30 +01:00
o ( initializedModel . allRecipients ( ) . length ) . equals ( 2 ) (
"Only MailAddresses with a valid address will be accepted as recipients" ,
)
2020-09-18 14:41:31 +02:00
o ( initializedModel . toRecipients ( ) . length ) . equals ( 1 )
o ( initializedModel . ccRecipients ( ) . length ) . equals ( 1 )
o ( initializedModel . bccRecipients ( ) . length ) . equals ( 0 )
o ( initializedModel . getSender ( ) ) . equals ( DEFAULT_SENDER_FOR_TESTING )
o ( model . isConfidential ( ) ) . equals ( true )
o ( model . containsExternalRecipients ( ) ) . equals ( true )
o ( initializedModel . getAttachments ( ) . length ) . equals ( 0 )
o ( initializedModel . hasMailChanged ( ) ) . equals ( false ) ( "initialization should not flag mail changed" )
} )
} )
2020-11-03 08:42:25 +01:00
o . spec ( "Adding and removing recipients" , function ( ) {
o . beforeEach ( async function ( ) {
2020-09-18 14:41:31 +02:00
await model . initWithTemplate ( { } , "" , "" , [ ] , false , "" )
} )
2022-02-03 14:55:40 +01:00
o ( "lazily resolved recipient will set it's promise to null when resolved" , async function ( ) {
2020-09-18 14:41:31 +02:00
const recipient = {
name : "sanchez" ,
address : "123@test.com" ,
2022-01-07 15:58:30 +01:00
contact : null ,
2020-09-18 14:41:31 +02:00
}
2022-01-07 15:58:30 +01:00
const [ r1 ] = model . addOrGetRecipient ( RecipientField . TO , recipient , false )
2022-02-03 14:55:40 +01:00
o ( r1 . contact ) . equals ( null ) ( "Contact not resolved yet, it's null" )
o ( r1 . resolveContactPromise ) . notEquals ( null ) ( "Contact not resolved yet, promise is non null" )
await r1 . resolveContactPromise
o ( r1 . contact ) . notEquals ( null ) ( "Contact has resolved and is no longer null" )
o ( r1 . resolveContactPromise ) . equals ( null ) ( "Contact has resolved, so it's promise is now null" )
} )
o ( "adding duplicate to-recipient" , async function ( ) {
const recipient = {
name : "sanchez" ,
address : "123@test.com" ,
contact : null ,
}
const [ r1 ] = model . addOrGetRecipient ( RecipientField . TO , recipient , false )
o ( model . addOrGetRecipient ( RecipientField . TO , recipient , false ) [ 0 ] === r1 ) . equals ( true ) ( "Adding same recipient a second time will return the same as the first time" )
2020-09-18 14:41:31 +02:00
o ( model . toRecipients ( ) . length ) . equals ( 1 )
o ( model . ccRecipients ( ) . length ) . equals ( 0 )
o ( model . bccRecipients ( ) . length ) . equals ( 0 )
2022-02-03 14:55:40 +01:00
2020-09-18 14:41:31 +02:00
await r1 . resolveContactPromise
2022-02-03 14:55:40 +01:00
o ( r1 . contact ! . mailAddresses [ 0 ] . address ) . equals ( recipient . address )
2020-09-18 14:41:31 +02:00
} )
2022-02-03 14:55:40 +01:00
o ( "add different to-recipients" , async function ( ) {
2020-09-18 14:41:31 +02:00
const pablo = {
name : "pablo" ,
address : "pablo94@test.co.uk" ,
2022-01-07 15:58:30 +01:00
contact : null ,
2020-09-18 14:41:31 +02:00
}
const cortez = {
name : "cortez" ,
address : "c.asd@test.net" ,
2022-01-07 15:58:30 +01:00
contact : null ,
2020-09-18 14:41:31 +02:00
}
2022-01-07 15:58:30 +01:00
const [ r1 ] = model . addOrGetRecipient ( RecipientField . TO , pablo , false )
const [ r2 ] = model . addOrGetRecipient ( RecipientField . TO , cortez , false )
2020-09-18 14:41:31 +02:00
o ( r1 === r2 ) . equals ( false )
o ( model . toRecipients ( ) . length ) . equals ( 2 )
o ( model . ccRecipients ( ) . length ) . equals ( 0 )
o ( model . bccRecipients ( ) . length ) . equals ( 0 )
2022-02-03 14:55:40 +01:00
2020-09-18 14:41:31 +02:00
await r1 . resolveContactPromise
2022-02-03 14:55:40 +01:00
o ( r1 . contact ! . mailAddresses [ 0 ] . address ) . equals ( pablo . address )
2020-09-18 14:41:31 +02:00
await r2 . resolveContactPromise
2022-02-03 14:55:40 +01:00
o ( r2 . contact ! . mailAddresses [ 0 ] . address ) . equals ( cortez . address )
2020-09-18 14:41:31 +02:00
} )
2020-11-03 08:42:25 +01:00
o ( "add duplicate recipients to different fields" , async function ( ) {
2020-09-18 14:41:31 +02:00
const recipient = {
name : "sanchez" ,
address : "123@test.com" ,
2022-01-07 15:58:30 +01:00
contact : null ,
2020-09-18 14:41:31 +02:00
}
2022-01-07 15:58:30 +01:00
const [ r1 ] = model . addOrGetRecipient ( RecipientField . TO , recipient , false )
const [ r2 ] = model . addOrGetRecipient ( RecipientField . CC , recipient , false )
2020-09-18 14:41:31 +02:00
o ( r1 === r2 ) . equals ( false )
o ( model . toRecipients ( ) . length ) . equals ( 1 )
o ( model . ccRecipients ( ) . length ) . equals ( 1 )
o ( model . bccRecipients ( ) . length ) . equals ( 0 )
await r1 . resolveContactPromise
2022-02-03 14:55:40 +01:00
o ( r1 . contact ! . mailAddresses [ 0 ] . address ) . equals ( recipient . address )
2020-09-18 14:41:31 +02:00
await r2 . resolveContactPromise
2022-02-03 14:55:40 +01:00
o ( r2 . contact ! . mailAddresses [ 0 ] . address ) . equals ( recipient . address )
2020-09-18 14:41:31 +02:00
} )
} )
o . spec ( "Sending" , function ( ) {
o ( "completely blank email" , async function ( ) {
const method = MailMethod . NONE
2022-02-03 14:55:40 +01:00
const getConfirmation = func < ( ) = > Promise < boolean > > ( )
2021-06-21 17:47:54 +02:00
const e = await assertThrows ( UserError , ( ) = > model . send ( method , getConfirmation ) )
2021-07-20 12:31:30 +02:00
o ( e ? . message ) . equals ( lang . get ( "noRecipients_msg" ) )
2022-02-03 14:55:40 +01:00
verify ( getConfirmation ( ) , { times : 0 } )
verify ( mailFacade . sendDraft ( anything ( ) , anything ( ) , anything ( ) ) , { times : 0 } )
verify ( mailFacade . createDraft ( anything ( ) ) , { times : 0 } )
verify ( mailFacade . updateDraft ( anything ( ) ) , { times : 0 } )
2020-09-18 14:41:31 +02:00
} )
o ( "blank subject no confirm" , async function ( ) {
2022-01-07 15:58:30 +01:00
await model . addOrGetRecipient ( RecipientField . TO , {
name : "test" ,
address : "test@address.com" ,
contact : null ,
} ) [ 0 ] . resolveContactPromise
2020-09-18 14:41:31 +02:00
const method = MailMethod . NONE
2022-02-03 14:55:40 +01:00
const getConfirmation = func < ( ) = > Promise < boolean > > ( )
2020-09-18 14:41:31 +02:00
const r = await model . send ( method , getConfirmation )
o ( r ) . equals ( false )
2022-02-03 14:55:40 +01:00
verify ( getConfirmation ( ) , { times : 0 } )
verify ( mailFacade . sendDraft ( anything ( ) , anything ( ) , anything ( ) ) , { times : 0 } )
verify ( mailFacade . createDraft ( anything ( ) ) , { times : 0 } )
verify ( mailFacade . updateDraft ( anything ( ) ) , { times : 0 } )
2020-09-18 14:41:31 +02:00
} )
o ( "confidential missing password" , async function ( ) {
2022-01-07 15:58:30 +01:00
await model . addOrGetRecipient ( RecipientField . TO , {
name : "test" ,
address : "test@address.com" ,
contact : null ,
} ) [ 0 ] . resolveContactPromise
2020-09-18 14:41:31 +02:00
model . setConfidential ( true )
const method = MailMethod . NONE
2022-02-03 14:55:40 +01:00
const getConfirmation = func < ( TranslationKey ) = > Promise < boolean > > ( )
when ( getConfirmation ( anything ( ) ) ) . thenResolve ( true )
2021-06-21 17:47:54 +02:00
const e = await assertThrows ( UserError , ( ) = > model . send ( method , getConfirmation ) )
2021-07-20 12:31:30 +02:00
o ( e ? . message ) . equals ( lang . get ( "noPreSharedPassword_msg" ) )
2022-02-03 14:55:40 +01:00
verify ( mailFacade . sendDraft ( anything ( ) , anything ( ) , anything ( ) ) , { times : 0 } )
verify ( mailFacade . createDraft ( anything ( ) ) , { times : 0 } )
verify ( mailFacade . updateDraft ( anything ( ) ) , { times : 0 } )
2020-09-18 14:41:31 +02:00
} )
o ( "confidential weak password no confirm" , async function ( ) {
2022-01-07 15:58:30 +01:00
const recipient = {
name : "test" ,
address : "test@address.com" ,
contact : null ,
}
model . addOrGetRecipient ( RecipientField . TO , recipient )
2020-09-18 14:41:31 +02:00
model . setSubject ( "subject" )
model . setPassword ( "test@address.com" , "abc" )
o ( model . getPassword ( recipient . address ) ) . equals ( "abc" )
model . setConfidential ( true )
const method = MailMethod . NONE
2022-02-03 14:55:40 +01:00
const getConfirmation = func < ( TranslationKey ) = > Promise < boolean > > ( )
when ( getConfirmation ( anything ( ) ) ) . thenResolve ( false )
2020-09-18 14:41:31 +02:00
const r = await model . send ( method , getConfirmation )
o ( r ) . equals ( false )
2022-02-03 14:55:40 +01:00
verify ( mailFacade . sendDraft ( anything ( ) , anything ( ) , anything ( ) ) , { times : 0 } )
verify ( mailFacade . createDraft ( anything ( ) ) , { times : 0 } )
verify ( mailFacade . updateDraft ( anything ( ) ) , { times : 0 } )
2020-09-18 14:41:31 +02:00
} )
o ( "confidential weak password confirm" , async function ( ) {
2022-01-07 15:58:30 +01:00
const recipient = {
name : "test" ,
address : "test@address.com" ,
contact : null ,
}
model . addOrGetRecipient ( RecipientField . TO , recipient )
2020-09-18 14:41:31 +02:00
model . setSubject ( "did you get that thing i sent ya?" )
const password = WEAK_PASSWORD
model . setPassword ( "test@address.com" , password )
o ( model . getPassword ( recipient . address ) ) . equals ( password )
model . setConfidential ( true )
const method = MailMethod . NONE
2022-02-03 14:55:40 +01:00
const getConfirmation = func < ( TranslationKey ) = > Promise < boolean > > ( )
when ( getConfirmation ( anything ( ) ) ) . thenResolve ( true )
2020-09-18 14:41:31 +02:00
const r = await model . send ( method , getConfirmation )
o ( r ) . equals ( true )
2022-02-03 14:55:40 +01:00
verify ( mailFacade . sendDraft ( anything ( ) , anything ( ) , anything ( ) ) , { times : 1 } )
verify ( mailFacade . createDraft ( anything ( ) ) , { times : 1 } )
verify ( mailFacade . updateDraft ( anything ( ) ) , { times : 0 } )
const contact = model . getRecipientList ( RecipientField . TO ) [ 0 ] . contact !
o ( contact . presharedPassword ) . equals ( password )
2020-09-18 14:41:31 +02:00
} )
2022-02-03 14:55:40 +01:00
o ( "correct password will be returned from getPassword after calling setPassword" , function ( ) {
model . setPassword ( "address1" , "password1" )
model . setPassword ( "address2" , "password2" )
o ( model . getPassword ( "address2" ) ) . equals ( "password2" )
o ( model . getPassword ( "address1" ) ) . equals ( "password1" )
} )
2020-09-18 14:41:31 +02:00
o ( "confidential strong password" , async function ( ) {
const address = "test@address.com"
2022-01-07 15:58:30 +01:00
const recipient = {
name : "test" ,
address : address ,
contact : null ,
}
model . addOrGetRecipient ( RecipientField . TO , recipient )
2020-09-18 14:41:31 +02:00
model . setSubject ( "did you get that thing i sent ya?" )
const password = STRONG_PASSWORD
model . setPassword ( address , password )
model . setConfidential ( true )
const method = MailMethod . NONE
2022-02-03 14:55:40 +01:00
const getConfirmation = func < ( TranslationKey ) = > Promise < boolean > > ( )
2020-09-18 14:41:31 +02:00
const r = await model . send ( method , getConfirmation )
o ( r ) . equals ( true )
2022-02-03 14:55:40 +01:00
verify ( getConfirmation ( anything ) , { times : 0 } )
verify ( mailFacade . sendDraft ( anything ( ) , anything ( ) , anything ( ) ) , { times : 1 } )
verify ( mailFacade . createDraft ( anything ( ) ) , { times : 1 } )
verify ( mailFacade . updateDraft ( anything ( ) ) , { times : 0 } )
const contact = model . getRecipientList ( RecipientField . TO ) [ 0 ] . contact !
o ( contact . presharedPassword ) . equals ( password )
2020-09-18 14:41:31 +02:00
} )
2022-02-03 14:55:40 +01:00
o ( "when a recipient doesn't have an existing contact, it will be created" , async function ( ) {
const getConfirmation = func < ( TranslationKey ) = > Promise < boolean > > ( )
const [ recipientInfo , resolveContactPromise ] = model . addOrGetRecipient (
RecipientField . TO ,
2020-09-18 14:41:31 +02:00
{
2022-02-03 14:55:40 +01:00
name : "chippie" ,
address : "chippie@cinco.net" ,
contact : null
}
)
model . setPassword ( "chippie@cinco.net" , STRONG_PASSWORD )
model . setSubject ( "did you get that thing i sent ya?" )
model . setConfidential ( true )
await model . send ( MailMethod . NONE , getConfirmation )
verify ( entity . setup ( "contactListId" , argThat ( ( contact ) = > isSameTypeRef ( ContactTypeRef , contact . _type ) ) ) )
verify ( entity . update ( anything ( ) ) , { times : 0 } )
} )
o ( "when a recipient has an existing contact, it won't be created or updated" , async function ( ) {
const getConfirmation = func < ( TranslationKey ) = > Promise < boolean > > ( )
const [ recipientInfo , resolveContactPromise ] = model . addOrGetRecipient (
RecipientField . TO ,
2020-09-18 14:41:31 +02:00
{
2022-02-03 14:55:40 +01:00
name : "chippie" ,
address : "chippie@cinco.net" ,
2022-01-07 15:58:30 +01:00
contact : createContact ( {
2020-09-18 14:41:31 +02:00
_id : testIdGenerator.newIdTuple ( ) ,
2022-02-03 14:55:40 +01:00
firstName : "my" ,
lastName : "chippie" ,
presharedPassword : STRONG_PASSWORD ,
} )
}
)
2020-09-18 14:41:31 +02:00
model . setSubject ( "did you get that thing i sent ya?" )
model . setConfidential ( true )
2022-02-03 14:55:40 +01:00
await model . send ( MailMethod . NONE , getConfirmation )
verify ( entity . setup ( anything ( ) , anything ( ) , anything ( ) ) , { times : 0 } )
verify ( entity . update ( anything ( ) ) , { times : 0 } )
} )
o ( "when a recipient has an existing contact, and the saved password changes, then the contact will be updated" , async function ( ) {
const getConfirmation = func < ( TranslationKey ) = > Promise < boolean > > ( )
const contact = createContact ( {
_id : testIdGenerator.newIdTuple ( ) ,
firstName : "my" ,
lastName : "chippie" ,
presharedPassword : "weak password" ,
2020-09-18 14:41:31 +02:00
} )
2022-02-03 14:55:40 +01:00
const [ recipientInfo , resolveContactPromise ] = model . addOrGetRecipient (
RecipientField . TO ,
{
name : "chippie" ,
address : "chippie@cinco.net" ,
contact
}
2022-01-07 15:58:30 +01:00
)
2022-02-03 14:55:40 +01:00
model . setPassword ( "chippie@cinco.net" , STRONG_PASSWORD )
model . setSubject ( "did you get that thing i sent ya?" )
model . setConfidential ( true )
await model . send ( MailMethod . NONE , getConfirmation )
verify ( entity . update ( contact ) , { times : 1 } )
2020-09-18 14:41:31 +02:00
} )
} )
o . spec ( "Entity Event Updates" , function ( ) {
let existingContact
2022-02-03 14:55:40 +01:00
2020-11-03 08:42:25 +01:00
o . beforeEach ( async function ( ) {
2022-02-03 14:55:40 +01:00
2020-09-18 14:41:31 +02:00
existingContact = createContact ( {
_id : testIdGenerator.newIdTuple ( ) ,
firstName : "james" ,
lastName : "hetfield" ,
} )
2022-02-03 14:55:40 +01:00
2020-09-18 14:41:31 +02:00
const recipients = [
{
2022-01-07 15:58:30 +01:00
name : "paul gilbert" ,
address : "paul@gmail.com" ,
contact : null ,
} ,
{
name : "james hetfield" ,
address : "james@tutanota.com" ,
contact : existingContact ,
} ,
2020-09-18 14:41:31 +02:00
]
2022-01-07 15:58:30 +01:00
await model . initWithTemplate (
{
to : recipients ,
} ,
"they all drink lemonade" ,
"" ,
)
2020-09-18 14:41:31 +02:00
} )
2022-02-03 14:55:40 +01:00
2020-09-18 14:41:31 +02:00
o ( "nonmatching event" , async function ( ) {
await model . _handleEntityEvent ( downcast ( CustomerAccountCreateDataTypeRef ) )
await model . _handleEntityEvent ( downcast ( UserTypeRef ) )
await model . _handleEntityEvent ( downcast ( CustomerTypeRef ) )
await model . _handleEntityEvent ( downcast ( NotificationMailTypeRef ) )
await model . _handleEntityEvent ( downcast ( ChallengeTypeRef ) )
await model . _handleEntityEvent ( downcast ( MailTypeRef ) )
2022-02-03 14:55:40 +01:00
verify ( entity . load ( anything ( ) , anything ( ) , anything ( ) , anything ( ) ) , { times : 0 } )
2020-09-18 14:41:31 +02:00
} )
2022-02-03 14:55:40 +01:00
2020-09-18 14:41:31 +02:00
o ( "contact updated email kept" , async function ( ) {
const { app , type } = ContactTypeRef
const [ instanceListId , instanceId ] = existingContact . _id
const contactForUpdate = {
firstName : "newfirstname" ,
lastName : "newlastname" ,
2021-12-07 15:30:53 +01:00
mailAddresses : [
2022-01-07 15:58:30 +01:00
createMailAddress ( {
address : "james@tutanota.com" ,
} ) ,
createMailAddress ( {
address : "address2@hotmail.com" ,
} ) ,
] ,
2020-09-18 14:41:31 +02:00
}
2022-02-03 14:55:40 +01:00
when ( entity . load ( ContactTypeRef , argThat ( ( id ) = > isSameId ( id , existingContact . _id ) ) ) )
. thenResolve ( createContact ( Object . assign ( { _id : existingContact._id } as Contact , contactForUpdate ) ) )
2022-01-07 15:58:30 +01:00
await model . _handleEntityEvent (
2022-02-03 14:55:40 +01:00
{
2022-01-07 15:58:30 +01:00
application : app ,
type ,
operation : OperationType.UPDATE ,
instanceListId ,
instanceId ,
2022-02-03 14:55:40 +01:00
} ,
2022-01-07 15:58:30 +01:00
)
2020-09-18 14:41:31 +02:00
o ( model . allRecipients ( ) . length ) . equals ( 2 )
2022-01-07 15:58:30 +01:00
const updatedRecipient = model
. allRecipients ( )
. find ( r = > r . contact && isSameId ( r . contact . _id , existingContact . _id ) )
2020-09-18 14:41:31 +02:00
o ( updatedRecipient && updatedRecipient . name ) . equals ( getContactDisplayName ( downcast ( contactForUpdate ) ) )
} )
o ( "contact updated email removed or changed" , async function ( ) {
const { app , type } = ContactTypeRef
const [ instanceListId , instanceId ] = existingContact . _id
const contactForUpdate = {
firstName : "james" ,
lastName : "hetfield" ,
2022-01-07 15:58:30 +01:00
mailAddresses : [
createMailAddress ( {
address : "nolongerjames@hotmail.com" ,
} ) ,
] ,
2020-09-18 14:41:31 +02:00
}
2022-02-03 14:55:40 +01:00
when ( entity . load ( ContactTypeRef , existingContact . _id ) )
. thenResolve (
createContact ( Object . assign ( {
_id : existingContact._id ,
} as Contact , contactForUpdate ) )
)
2022-01-07 15:58:30 +01:00
await model . _handleEntityEvent (
2022-02-03 14:55:40 +01:00
{
2022-01-07 15:58:30 +01:00
application : app ,
type ,
operation : OperationType.UPDATE ,
instanceListId ,
instanceId ,
2022-02-03 14:55:40 +01:00
} ,
2022-01-07 15:58:30 +01:00
)
2020-09-18 14:41:31 +02:00
o ( model . allRecipients ( ) . length ) . equals ( 1 )
2022-01-07 15:58:30 +01:00
const updatedContact = model
. allRecipients ( )
. find ( r = > r . contact && isSameId ( r . contact . _id , existingContact . _id ) )
2022-02-03 14:55:40 +01:00
o ( updatedContact ? ? null ) . equals ( null )
2020-09-18 14:41:31 +02:00
} )
o ( "contact removed" , async function ( ) {
const { app , type } = ContactTypeRef
const [ instanceListId , instanceId ] = existingContact . _id
2022-01-07 15:58:30 +01:00
await model . _handleEntityEvent (
2022-02-03 14:55:40 +01:00
{
2022-01-07 15:58:30 +01:00
application : app ,
type ,
operation : OperationType.DELETE ,
instanceListId ,
instanceId ,
2022-02-03 14:55:40 +01:00
} ,
2022-01-07 15:58:30 +01:00
)
2020-09-18 14:41:31 +02:00
o ( model . allRecipients ( ) . length ) . equals ( 1 )
2022-01-07 15:58:30 +01:00
const updatedContact = model
. allRecipients ( )
. find ( r = > r . contact && isSameId ( r . contact . _id , existingContact . _id ) )
2020-09-18 14:41:31 +02:00
o ( updatedContact == null ) . equals ( true )
} )
2021-02-04 10:46:11 +01:00
o ( "too many to recipients dont confirm" , async function ( ) {
2022-01-07 15:58:30 +01:00
const recipients = {
2022-02-03 14:55:40 +01:00
to : [ ] as { name : string , address : string } [ ] ,
2022-01-07 15:58:30 +01:00
}
2021-02-04 10:46:11 +01:00
for ( let i = 0 ; i < TOO_MANY_VISIBLE_RECIPIENTS ; ++ i ) {
recipients . to . push ( {
name : ` person ${ i } ` ,
2022-01-07 15:58:30 +01:00
address : ` person ${ i } @tutanota.de ` ,
2021-02-04 10:46:11 +01:00
} )
}
2022-01-07 15:58:30 +01:00
2021-02-04 10:46:11 +01:00
const subject = "subyekt"
const body = "bodie"
2022-02-03 14:55:40 +01:00
const getConfirmation = func < ( TranslationKey ) = > Promise < boolean > > ( )
when ( getConfirmation ( "manyRecipients_msg" ) ) . thenResolve ( false )
2021-02-04 10:46:11 +01:00
await model . initWithTemplate ( recipients , subject , body , [ ] , false , "eggs@tutanota.de" )
o ( await model . send ( MailMethod . NONE , getConfirmation ) ) . equals ( false )
} )
o ( "too many to recipients confirm" , async function ( ) {
2022-01-07 15:58:30 +01:00
const recipients = {
2022-02-03 14:55:40 +01:00
to : [ ] as { name : string , address : string } [ ] ,
2022-01-07 15:58:30 +01:00
}
2021-02-04 10:46:11 +01:00
for ( let i = 0 ; i < TOO_MANY_VISIBLE_RECIPIENTS ; ++ i ) {
recipients . to . push ( {
name : ` person ${ i } ` ,
2022-01-07 15:58:30 +01:00
address : ` person ${ i } @tutanota.de ` ,
2021-02-04 10:46:11 +01:00
} )
}
2022-01-07 15:58:30 +01:00
2021-02-04 10:46:11 +01:00
const subject = "subyekt"
const body = "bodie"
2022-02-03 14:55:40 +01:00
const getConfirmation = func < ( TranslationKey ) = > Promise < boolean > > ( )
when ( getConfirmation ( "manyRecipients_msg" ) ) . thenResolve ( true )
2021-02-04 10:46:11 +01:00
await model . initWithTemplate ( recipients , subject , body , [ ] , false , "eggs@tutanota.de" )
2022-02-03 14:55:40 +01:00
2021-02-04 10:46:11 +01:00
o ( await model . send ( MailMethod . NONE , getConfirmation ) ) . equals ( true )
} )
o ( "too many cc recipients dont confirm" , async function ( ) {
2022-01-07 15:58:30 +01:00
const recipients = {
2022-02-03 14:55:40 +01:00
cc : [ ] as { name : string , address : string } [ ] ,
2022-01-07 15:58:30 +01:00
}
2021-02-04 10:46:11 +01:00
for ( let i = 0 ; i < TOO_MANY_VISIBLE_RECIPIENTS ; ++ i ) {
recipients . cc . push ( {
name : ` person ${ i } ` ,
2022-01-07 15:58:30 +01:00
address : ` person ${ i } @tutanota.de ` ,
2021-02-04 10:46:11 +01:00
} )
}
2022-01-07 15:58:30 +01:00
2021-02-04 10:46:11 +01:00
const subject = "subyekt"
const body = "bodie"
2022-02-03 14:55:40 +01:00
const getConfirmation = func < ( TranslationKey ) = > Promise < boolean > > ( )
when ( getConfirmation ( "manyRecipients_msg" ) ) . thenResolve ( false )
2021-02-04 10:46:11 +01:00
await model . initWithTemplate ( recipients , subject , body , [ ] , false , "eggs@tutanota.de" )
o ( await model . send ( MailMethod . NONE , getConfirmation ) ) . equals ( false )
} )
o ( "too many cc recipients confirm" , async function ( ) {
2022-01-07 15:58:30 +01:00
const recipients = {
2022-02-03 14:55:40 +01:00
cc : [ ] as { name : string , address : string } [ ] ,
2022-01-07 15:58:30 +01:00
}
2021-02-04 10:46:11 +01:00
for ( let i = 0 ; i < TOO_MANY_VISIBLE_RECIPIENTS ; ++ i ) {
recipients . cc . push ( {
name : ` person ${ i } ` ,
2022-01-07 15:58:30 +01:00
address : ` person ${ i } @tutanota.de ` ,
2021-02-04 10:46:11 +01:00
} )
}
2022-01-07 15:58:30 +01:00
2021-02-04 10:46:11 +01:00
const subject = "subyekt"
const body = "bodie"
2022-02-03 14:55:40 +01:00
const getConfirmation = func < ( TranslationKey ) = > Promise < boolean > > ( )
when ( getConfirmation ( "manyRecipients_msg" ) ) . thenResolve ( true )
2021-02-04 10:46:11 +01:00
await model . initWithTemplate ( recipients , subject , body , [ ] , false , "eggs@tutanota.de" )
o ( await model . send ( MailMethod . NONE , getConfirmation ) ) . equals ( true )
} )
2020-09-18 14:41:31 +02:00
} )
2022-01-07 15:58:30 +01:00
} )