def sendEmail(self, emails, mass_type='SingleEmailMessage'): """ Send one or more emails from Salesforce. Parameters: emails - a dictionary or list of dictionaries, each representing a single email as described by https://www.salesforce.com/us/developer/docs/api/Content/sforce_api_calls_sendemail.htm massType - 'SingleEmailMessage' or 'MassEmailMessage'. MassEmailMessage is used for mailmerge of up to 250 recepients in a single pass. Note: Newly created Salesforce Sandboxes default to System email only. In this situation, sendEmail() will fail with NO_MASS_MAIL_PERMISSION. """ preparedEmails = _prepareSObjects(emails) if isinstance(preparedEmails,dict): # If root element is a dict, then this is a single object not an array del preparedEmails['fieldsToNull'] else: # else this is an array, and each elelment should be prepped. for listitems in preparedEmails: del listitems['fieldsToNull'] res = BaseClient.sendEmail(self, preparedEmails, mass_type) if type(res) not in (TupleType, ListType): res = [res] data = list() for resu in res: d = dict() data.append(d) d['success'] = success = _bool(resu[_tPartnerNS.success]) if not success: d['errors'] = [_extractError(e) for e in resu[_tPartnerNS.errors:]] else: d['errors'] = list() return data
def query(self, *args, **kw): if self.cacheTypeDescriptions: typeDescs = self.typeDescs else: typeDescs = {} if len(args) == 1: # full query string queryString = args[0] elif len(args) == 2: # BBB: fields, sObjectType queryString = 'select %s from %s' % (args[0], args[1]) if 'conditionalExpression' in kw: # BBB: fields, sObjectType, conditionExpression as kwarg queryString += ' where %s' % (kw['conditionalExpression']) elif len(args) == 3: # BBB: fields, sObjectType, conditionExpression as positional arg whereClause = args[2] and (' where %s' % args[2]) or '' queryString = 'select %s from %s%s' % (args[0], args[1], whereClause) else: raise RuntimeError, "Wrong number of arguments to query method." res = BaseClient.query(self, queryString) # calculate the union of the sets of record types from each record types = reduce(lambda a,b: a|b, [getRecordTypes(r) for r in res[_tPartnerNS.records:]], set()) new_types = types - set(typeDescs.keys()) if new_types: typeDescs.update(self.queryTypesDescriptions(new_types)) data = QueryRecordSet(records=[self._extractRecord(r, typeDescs) for r in res[_tPartnerNS.records:]], done=_bool(res[_tPartnerNS.done]), size=int(str(res[_tPartnerNS.size])), queryLocator = str(res[_tPartnerNS.queryLocator])) return data
def convert_leads(self, lead_converts): preparedLeadConverts = _prepareSObjects(lead_converts) if isinstance( preparedLeadConverts, dict ): del preparedLeadConverts['fieldsToNull'] else: for preppedConvert in preparedLeadConverts: del preppedConvert['fieldsToNull'] res = BaseClient.convertLeads(self, preparedLeadConverts) if type(res) not in (TupleType, ListType): res = [res] data = list() for resu in res: d = dict() data.append(d) d['success'] = success = _bool(resu[_tPartnerNS.success]) if not success: d['errors'] = [_extractError(e) for e in resu[_tPartnerNS.errors:]] else: d['errors'] = list() d['account_id'] = str(resu[_tPartnerNS.accountId]) d['contact_id'] = str(resu[_tPartnerNS.contactId]) d['lead_id'] = str(resu[_tPartnerNS.leadId]) d['opportunity_id'] = str(resu[_tPartnerNS.opportunityId]) return data
def login(self, username, passwd): res = BaseClient.login(self, username, passwd) data = dict() data['passwordExpired'] = _bool(res[_tPartnerNS.passwordExpired]) data['serverUrl'] = str(res[_tPartnerNS.serverUrl]) data['sessionId'] = str(res[_tPartnerNS.sessionId]) data['userId'] = str(res[_tPartnerNS.userId]) data['userInfo'] = _extractUserInfo(res[_tPartnerNS.userInfo]) return data
def describeSObjects(self, sObjectTypes): res = BaseClient.describeSObjects(self, sObjectTypes) if type(res) not in (TupleType, ListType): res = [res] data = list() for r in res: d = dict() d['activateable'] = _bool(r[_tPartnerNS.activateable]) rawreldata = r[_tPartnerNS.ChildRelationships:] relinfo = [_extractChildRelInfo(cr) for cr in rawreldata] d['ChildRelationships'] = relinfo d['createable'] = _bool(r[_tPartnerNS.createable]) d['custom'] = _bool(r[_tPartnerNS.custom]) try: d['customSetting'] = _bool(r[_tPartnerNS.customSetting]) except KeyError: pass d['deletable'] = _bool(r[_tPartnerNS.deletable]) d['deprecatedAndHidden'] = _bool( r[_tPartnerNS.deprecatedAndHidden]) try: d['feedEnabled'] = _bool(r[_tPartnerNS.feedEnabled]) except KeyError: pass fields = r[_tPartnerNS.fields:] fields = [_extractFieldInfo(f) for f in fields] field_map = dict() for f in fields: field_map[f.name] = f d['fields'] = field_map d['keyPrefix'] = str(r[_tPartnerNS.keyPrefix]) d['label'] = str(r[_tPartnerNS.label]) d['labelPlural'] = str(r[_tPartnerNS.labelPlural]) d['layoutable'] = _bool(r[_tPartnerNS.layoutable]) d['mergeable'] = _bool(r[_tPartnerNS.mergeable]) d['name'] = str(r[_tPartnerNS.name]) d['queryable'] = _bool(r[_tPartnerNS.queryable]) d['recordTypeInfos'] = ([ _extractRecordTypeInfo(rti) for rti in r[_tPartnerNS.recordTypeInfos:] ]) d['replicateable'] = _bool(r[_tPartnerNS.replicateable]) d['retrieveable'] = _bool(r[_tPartnerNS.retrieveable]) d['searchable'] = _bool(r[_tPartnerNS.searchable]) try: d['triggerable'] = _bool(r[_tPartnerNS.triggerable]) except KeyError: pass d['undeletable'] = _bool(r[_tPartnerNS.undeletable]) d['updateable'] = _bool(r[_tPartnerNS.updateable]) d['urlDetail'] = str(r[_tPartnerNS.urlDetail]) d['urlEdit'] = str(r[_tPartnerNS.urlEdit]) d['urlNew'] = str(r[_tPartnerNS.urlNew]) data.append(SObject(**d)) return data
def describeSObjects(self, sObjectTypes): res = BaseClient.describeSObjects(self, sObjectTypes) if type(res) not in (TupleType, ListType): res = [res] data = list() for r in res: d = dict() d['activateable'] = _bool(r[_tPartnerNS.activateable]) rawreldata = r[_tPartnerNS.ChildRelationships,] relinfo = [_extractChildRelInfo(cr) for cr in rawreldata] d['ChildRelationships'] = relinfo d['createable'] = _bool(r[_tPartnerNS.createable]) d['custom'] = _bool(r[_tPartnerNS.custom]) try: d['customSetting'] = _bool(r[_tPartnerNS.customSetting]) except KeyError: pass d['deletable'] = _bool(r[_tPartnerNS.deletable]) d['deprecatedAndHidden'] = _bool( r[_tPartnerNS.deprecatedAndHidden] ) try: d['feedEnabled'] = _bool(r[_tPartnerNS.feedEnabled]) except KeyError: pass fields = r[_tPartnerNS.fields,] fields = [_extractFieldInfo(f) for f in fields] field_map = dict() for f in fields: field_map[f.name] = f d['fields'] = field_map d['keyPrefix'] = str(r[_tPartnerNS.keyPrefix]) d['label'] = str(r[_tPartnerNS.label]) d['labelPlural'] = str(r[_tPartnerNS.labelPlural]) d['layoutable'] = _bool(r[_tPartnerNS.layoutable]) d['mergeable'] = _bool(r[_tPartnerNS.mergeable]) d['name'] = str(r[_tPartnerNS.name]) d['queryable'] = _bool(r[_tPartnerNS.queryable]) d['recordTypeInfos'] = ([_extractRecordTypeInfo(rti) for rti in r[_tPartnerNS.recordTypeInfos,]]) d['replicateable'] = _bool(r[_tPartnerNS.replicateable]) d['retrieveable'] = _bool(r[_tPartnerNS.retrieveable]) d['searchable'] = _bool(r[_tPartnerNS.searchable]) try: d['triggerable'] = _bool(r[_tPartnerNS.triggerable]) except KeyError: pass d['undeletable'] = _bool(r[_tPartnerNS.undeletable]) d['updateable'] = _bool(r[_tPartnerNS.updateable]) d['urlDetail'] = str(r[_tPartnerNS.urlDetail]) d['urlEdit'] = str(r[_tPartnerNS.urlEdit]) d['urlNew'] = str(r[_tPartnerNS.urlNew]) data.append(SObject(**d)) return data
def describeTabs(self): res = BaseClient.describeTabs(self) data = list() for r in res: tabs = [_extractTab(t) for t in r[_tPartnerNS.tabs:]] d = dict(label=str(r[_tPartnerNS.label]), logoUrl=str(r[_tPartnerNS.logoUrl]), selected=_bool(r[_tPartnerNS.selected]), tabs=tabs) data.append(d) return data
def describeTabs(self): res = BaseClient.describeTabs(self) data = list() for r in res: tabs = [_extractTab(t) for t in r[_tPartnerNS.tabs:]] d = dict( label = str(r[_tPartnerNS.label]), logoUrl = str(r[_tPartnerNS.logoUrl]), selected = _bool(r[_tPartnerNS.selected]), tabs=tabs) data.append(d) return data
def getDeleted(self, sObjectType, start, end): res = BaseClient.getDeleted(self, sObjectType, start, end) res = res[_tPartnerNS.deletedRecords:] if type(res) not in (TupleType, ListType): res = [res] data = list() for r in res: d = dict( id = str(r[_tPartnerNS.id]), deletedDate = marshall('datetime', 'deletedDate', r, ns=_tPartnerNS)) data.append(d) return data
def getDeleted(self, sObjectType, start, end): res = BaseClient.getDeleted(self, sObjectType, start, end) res = res[_tPartnerNS.deletedRecords:] if type(res) not in (TupleType, ListType): res = [res] data = list() for r in res: d = dict(id=str(r[_tPartnerNS.id]), deletedDate=marshall('datetime', 'deletedDate', r, ns=_tPartnerNS)) data.append(d) return data
def search(self, sosl): if self.cacheTypeDescriptions: typeDescs = self.typeDescs else: typeDescs = {} res = BaseClient.search(self, sosl) # calculate the union of the sets of record types from each record if len(res): types = reduce(lambda a,b: a|b, [getRecordTypes(r) for r in res[_tPartnerNS.searchRecords]], set()) new_types = types - set(typeDescs.keys()) if new_types: typeDescs.update(self.queryTypesDescriptions(new_types)) return [self._extractRecord(r, typeDescs) for r in res[_tPartnerNS.searchRecords]] else: return []
def delete(self, ids): res = BaseClient.delete(self, ids) if type(res) not in (TupleType, ListType): res = [res] data = list() for r in res: d = dict() data.append(d) d['id'] = str(r[_tPartnerNS.id]) d['success'] = success = _bool(r[_tPartnerNS.success]) if not success: d['errors'] = [_extractError(e) for e in r[_tPartnerNS.errors:]] else: d['errors'] = list() return data
def delete(self, ids): res = BaseClient.delete(self, ids) if type(res) not in (TupleType, ListType): res = [res] data = list() for r in res: d = dict() data.append(d) d['id'] = str(r[_tPartnerNS.id]) d['success'] = success = _bool(r[_tPartnerNS.success]) if not success: d['errors'] = [_extractError(e) for e in r[_tPartnerNS.errors,]] else: d['errors'] = list() return data
def retrieve(self, fields, sObjectType, ids): resultSet = BaseClient.retrieve(self, fields, sObjectType, ids) type_data = self.describeSObjects(sObjectType)[0] if type(resultSet) not in (TupleType, ListType): if isnil(resultSet): resultSet = list() else: resultSet = [resultSet] fields = [f.strip() for f in fields.split(',')] data = list() for result in resultSet: d = dict() data.append(d) for fname in fields: d[fname] = type_data.marshall(fname, result) return data
def update(self, sObjects): preparedObjects = _prepareSObjects(sObjects) res = BaseClient.update(self, preparedObjects) if type(res) not in (TupleType, ListType): res = [res] data = list() for r in res: d = dict() data.append(d) d['id'] = str(r[_tPartnerNS.id]) d['success'] = success = _bool(r[_tPartnerNS.success]) if not success: d['errors'] = [_extractError(e) for e in r[_tPartnerNS.errors,]] else: d['errors'] = list() return data
def search(self, sosl): if self.cacheTypeDescriptions: typeDescs = self.typeDescs else: typeDescs = {} res = BaseClient.search(self, sosl) # calculate the union of the sets of record types from each record if len(res): types = reduce(lambda a, b: a | b, [getRecordTypes(r) for r in res[_tPartnerNS.searchRecords]], set()) new_types = types - set(typeDescs.keys()) if new_types: typeDescs.update(self.queryTypesDescriptions(new_types)) return [self._extractRecord(r, typeDescs) for r in res[_tPartnerNS.searchRecords]] else: return []
def update(self, sObjects): preparedObjects = _prepareSObjects(sObjects) res = BaseClient.update(self, preparedObjects) if type(res) not in (TupleType, ListType): res = [res] data = list() for r in res: d = dict() data.append(d) d['id'] = str(r[_tPartnerNS.id]) d['success'] = success = _bool(r[_tPartnerNS.success]) if not success: d['errors'] = [ _extractError(e) for e in r[_tPartnerNS.errors:] ] else: d['errors'] = list() return data
def queryMore(self, queryLocator): if self.cacheTypeDescriptions: typeDescs = self.typeDescs else: typeDescs = {} locator = queryLocator res = BaseClient.queryMore(self, locator) # calculate the union of the sets of record types from each record types = reduce(lambda a,b: a|b, [getRecordTypes(r) for r in res[_tPartnerNS.records:]], set()) new_types = types - set(typeDescs.keys()) if new_types: typeDescs.update(self.queryTypesDescriptions(new_types)) data = QueryRecordSet(records=[self._extractRecord(r, typeDescs) for r in res[_tPartnerNS.records:]], done=_bool(res[_tPartnerNS.done]), size=int(str(res[_tPartnerNS.size])), queryLocator = str(res[_tPartnerNS.queryLocator])) return data
def describeGlobal(self): res = BaseClient.describeGlobal(self) data = dict() data['encoding'] = str(res[_tPartnerNS.encoding]) data['maxBatchSize'] = int(str(res[_tPartnerNS.maxBatchSize])) sobjects = list() for r in res[_tPartnerNS.sobjects,]: d = dict() d['activateable'] = _bool(r[_tPartnerNS.activateable]) d['createable'] = _bool(r[_tPartnerNS.createable]) d['custom'] = _bool(r[_tPartnerNS.custom]) try: d['customSetting'] = _bool(r[_tPartnerNS.customSetting]) except KeyError: pass d['deletable'] = _bool(r[_tPartnerNS.deletable]) d['deprecatedAndHidden'] = _bool( r[_tPartnerNS.deprecatedAndHidden] ) try: d['feedEnabled'] = _bool(r[_tPartnerNS.feedEnabled]) except KeyError: pass d['keyPrefix'] = str(r[_tPartnerNS.keyPrefix]) d['label'] = str(r[_tPartnerNS.label]) d['labelPlural'] = str(r[_tPartnerNS.labelPlural]) d['layoutable'] = _bool(r[_tPartnerNS.layoutable]) d['mergeable'] = _bool(r[_tPartnerNS.mergeable]) d['name'] = str(r[_tPartnerNS.name]) d['queryable'] = _bool(r[_tPartnerNS.queryable]) d['replicateable'] = _bool(r[_tPartnerNS.replicateable]) d['retrieveable'] = _bool(r[_tPartnerNS.retrieveable]) d['searchable'] = _bool(r[_tPartnerNS.searchable]) d['triggerable'] = _bool(r[_tPartnerNS.triggerable]) d['undeletable'] = _bool(r[_tPartnerNS.undeletable]) d['updateable'] = _bool(r[_tPartnerNS.updateable]) sobjects.append(SObject(**d)) data['sobjects'] = sobjects data['types'] = [str(t) for t in res[_tPartnerNS.types,]] if not data['types']: # BBB for code written against API < 17.0 data['types'] = [s.name for s in data['sobjects']] return data
def sendEmail(self, emails, mass_type='SingleEmailMessage'): """ Send one or more emails from Salesforce. Parameters: emails - a dictionary or list of dictionaries, each representing a single email as described by https://www.salesforce.com /us/developer/docs/api/Content/sforce_api_calls_sendemail .htm massType - 'SingleEmailMessage' or 'MassEmailMessage'. MassEmailMessage is used for mailmerge of up to 250 recepients in a single pass. Note: Newly created Salesforce Sandboxes default to System email only. In this situation, sendEmail() will fail with NO_MASS_MAIL_PERMISSION. """ preparedEmails = _prepareSObjects(emails) if isinstance(preparedEmails, dict): # If root element is a dict, then this is a single object not an # array del preparedEmails['fieldsToNull'] else: # else this is an array, and each elelment should be prepped. for listitems in preparedEmails: del listitems['fieldsToNull'] res = BaseClient.sendEmail(self, preparedEmails, mass_type) if type(res) not in (TupleType, ListType): res = [res] data = list() for resu in res: d = dict() data.append(d) d['success'] = success = _bool(resu[_tPartnerNS.success]) if not success: d['errors'] = [ _extractError(e) for e in resu[_tPartnerNS.errors:] ] else: d['errors'] = list() return data
def convert_leads(self, lead_converts): preparedLeadConverts = _prepareSObjects(lead_converts) del preparedLeadConverts['fieldsToNull'] res = BaseClient.convertLeads(self, preparedLeadConverts) if type(res) not in (TupleType, ListType): res = [res] data = list() for resu in res: d = dict() data.append(d) d['success'] = success = _bool(resu[_tPartnerNS.success]) if not success: d['errors'] = [_extractError(e) for e in resu[_tPartnerNS.errors,]] else: d['errors'] = list() d['account_id'] = str(resu[_tPartnerNS.accountId]) d['contact_id'] = str(resu[_tPartnerNS.contactId]) d['lead_id'] = str(resu[_tPartnerNS.leadId]) d['opportunity_id'] = str(resu[_tPartnerNS.opportunityId]) return data
def query(self, *args, **kw): if self.cacheTypeDescriptions: typeDescs = self.typeDescs else: typeDescs = {} if len(args) == 1: # full query string queryString = args[0] elif len(args) == 2: # BBB: fields, sObjectType queryString = 'select %s from %s' % (args[0], args[1]) if 'conditionalExpression' in kw: # BBB: fields, sObjectType, # conditionExpression as kwarg queryString += ' where %s' % (kw['conditionalExpression']) elif len(args) == 3: # BBB: fields, sObjectType, conditionExpression # as positional arg whereClause = args[2] and (' where %s' % args[2]) or '' queryString = 'select %s from %s%s' % ( args[0], args[1], whereClause ) else: raise RuntimeError("Wrong number of arguments to query method.") res = BaseClient.query(self, queryString) # calculate the union of the sets of record types from each record types = reduce(lambda a, b: a | b, [getRecordTypes(r) for r in res[_tPartnerNS.records,]], set()) new_types = types - set(typeDescs.keys()) if new_types: typeDescs.update(self.queryTypesDescriptions(new_types)) data = QueryRecordSet( records=[self._extractRecord(r, typeDescs) for r in res[_tPartnerNS.records,]], done=_bool(res[_tPartnerNS.done]), size=int(str(res[_tPartnerNS.size])), queryLocator=str(res[_tPartnerNS.queryLocator]) ) return data
def queryMore(self, queryLocator): if self.cacheTypeDescriptions: typeDescs = self.typeDescs else: typeDescs = {} locator = queryLocator res = BaseClient.queryMore(self, locator) # calculate the union of the sets of record types from each record types = reduce(lambda a, b: a | b, [getRecordTypes(r) for r in res[_tPartnerNS.records,]], set()) new_types = types - set(typeDescs.keys()) if new_types: typeDescs.update(self.queryTypesDescriptions(new_types)) data = QueryRecordSet( records=[self._extractRecord(r, typeDescs) for r in res[_tPartnerNS.records,]], done=_bool(res[_tPartnerNS.done]), size=int(str(res[_tPartnerNS.size])), queryLocator=str(res[_tPartnerNS.queryLocator]) ) return data
def logout(self): res = BaseClient.logout(self) return res._name == _tPartnerNS.logoutResponse
def __init__(self, serverUrl=None, cacheTypeDescriptions=False): BaseClient.__init__(self, serverUrl=serverUrl) self.cacheTypeDescriptions = cacheTypeDescriptions if self.cacheTypeDescriptions: self.typeDescs = {}
def getUserInfo(self): res = BaseClient.getUserInfo(self) data = _extractUserInfo(res) return data
def getUpdated(self, sObjectType, start, end): res = BaseClient.getUpdated(self, sObjectType, start, end) res = res[_tPartnerNS.ids:] if type(res) not in (TupleType, ListType): res = [res] return [str(r) for r in res]