Contacts
`contacts.list`, `get`, `create`, `save`, `update`, `set_audiences`, `delete`, `delete_many`, `list_people`, `set_photo`, `remove_photo`, `block`, `unblock`, `list_threads` et `activity`.
Toutes les méthodes
from openemail import openemail page = openemail.contacts.list(limit=100)contact = openemail.contacts.get('[email protected]') saved = openemail.contacts.create({ 'email': '[email protected]', 'name': 'Grace Hopper', 'notes': 'Met at the compiler workshop',}) openemail.contacts.update(saved['email'], {'notes': None})openemail.contacts.set_audiences(saved['email'], { 'audienceIds': ['aud_4c1b8e2a7d9f05c36b4e8a71'],})openemail.contacts.delete(saved['email']) print(len(page['items']), page['hasMore'], contact['source'], contact['lastSeenAt'])Les plus récemment vus d'abord, et en dernier les contacts à qui rien n'a jamais été envoyé. source vaut auto quand la ligne a été écrite parce qu'un membre a envoyé un message à cette adresse depuis le compositeur de l'application, ce qui est une affirmation sensiblement différente de « quelqu'un l'a enregistrée ». Le courrier qui arrive d'une adresse n'écrit rien, et un envoi via cette API non plus.
Le carnet appartient à l'espace de travail plutôt qu'à une personne : un contact enregistré par un membre est donc le contact que voient tous les membres et toutes les clés. create écrit source à manual et place le contact dans l'audience par défaut au moment de l'écriture. Nommez vos propres listes dans audienceIds pour l'y ajouter dans le même appel, ce qui exige aussi audiences:write, ou ajoutez le contact plus tard avec openemail.audiences.add_contact. set_audiences dit exactement dans quelles listes se trouve un contact, en un seul appel.
Les adresses sont stockées en minuscules et le client encode celle que vous passez : [email protected] atteint donc la bonne ligne. L'adresse est l'identité : update ne peut donc pas la changer ; déplacer un contact, c'est un delete puis un create.
Paramètres : contacts.list
limitint- Combien de contacts renvoyer par page : un entier de 1 à 200, valant 50 par défaut. Il est converti, donc `'100'` venu d'une query string convient, et une valeur hors de l'intervalle donne un 422 plutôt qu'une valeur ramenée aux bornes.
cursorstr- Le `nextCursor` de la page précédente. N'en construisez jamais un vous-même : un curseur nommant un contact qui n'existe plus donne un 400 `invalid_cursor`, ce qui signifie que votre état de pagination est périmé et que le parcours doit repartir sans curseur.
sourceContactSource- `'manual'` pour les contacts que quelqu'un a enregistrés exprès, `'auto'` pour ceux qu'a enregistrés le compositeur de l'application. Omettez-le pour le carnet entier.
qstr- Cherche dans le nom et l'adresse, jusqu'à 200 caractères. Si rien ne correspond exactement sur la première page, des orthographes proches sont renvoyées à la place, et les pages suivantes continuent de chercher de la même façon.
Réponse : ContactResource
contacts.list renvoie un Page[ContactResource] : les lignes sont donc dans page['items'] et le parcours suit page['nextCursor'] tant que page['hasMore'] vaut True, ce que list_all et iterate font pour vous. get, create, save, update, set_audiences, set_photo et remove_photo renvoient chacun un ContactDetailResource, la même ligne plus audiences. Le carnet d'adresses n'a pas de limite, c'est pourquoi cette route pagine au lieu de renvoyer une liste qui s'arrêterait silencieusement à 200.
objectLiteral['contact']- Toujours la chaîne `contact`, sur les lignes de liste comme sur `get`.
emailstr- L'adresse, mise en minuscules à l'écriture pour que `[email protected]` et `[email protected]` ne fassent qu'un seul contact, et la clé que prend chaque méthode contacts, puisqu'aucun id de contact n'est exposé. Les lignes appartiennent à l'espace de travail plutôt qu'au membre ou à la clé qui les a écrites : chaque membre et chaque clé de l'espace lisent et écrivent donc un seul carnet d'adresses.
namestr | None- `None` quand aucun nom n'a jamais été enregistré pour l'adresse. Une écriture automatique n'en porte un que si l'en-tête fournissait autre chose que l'adresse elle-même, et elle ne peut jamais écraser un nom saisi par l'utilisateur.
sourceContactSource | str- `auto` signifie que la ligne a été écrite parce que l'utilisateur a envoyé du courrier à cette adresse ; `manual` signifie que quelqu'un l'a saisie à la main, une affirmation sensiblement différente, et un upsert ne rétrograde jamais `manual` en `auto`. Le courrier qui arrive d'une adresse n'écrit aucune ligne, délibérément : quelqu'un qui n'a jamais fait que vous écrire ne figure donc pas ici ; l'union reste ouverte parce que la colonne est du texte libre valant `manual` par défaut.
notesstr | None- Texte libre que quelqu'un a écrit sur cette personne, dans l'application ou via `update`, jamais généré. `None` quand personne n'en a écrit, et un `None` explicite sur `update` l'efface.
lastSeenAtstr | None- ISO-8601 UTC, avancé chaque fois qu'un membre écrit à cette adresse depuis le compositeur de l'application, et non quand du courrier en arrive, ce qui n'écrit rien. `None` sur un contact enregistré via `create` à qui rien n'a jamais été envoyé, et ceux-là arrivent en dernier dans l'ordre décroissant de `lastSeenAt` que renvoie cette route.
audienceslist[ContactAudienceResource]- Uniquement sur `get`, `create`, `save`, `update`, `set_audiences`, `set_photo` et `remove_photo`, jamais sur les lignes de liste. Chaque audience dont le contact fait partie, sous forme de dictionnaire avec `id`, `name` et `builtin`, celle par défaut comprise. `builtin` vaut `default` sur l'audience à laquelle appartient chaque contact et `None` sur une audience créée par quelqu'un : basez donc votre logique sur ce champ plutôt que sur le nom, que n'importe qui peut changer.
photoUrlstr | None- L'endroit où la photo du contact est servie, ou `None` quand le contact n'en a pas. `set_photo` la définit et chaque téléversement reçoit une nouvelle URL.
Définir les audiences d'un contact
set_audiences(email, {'audienceIds': [...]}) dit exactement dans quelles audiences se trouve un contact, en une seule requête. Le contact rejoint chaque audience indiquée où il n'est pas encore et quitte toutes les autres, et l'appel renvoie le ContactDetailResource après le changement. Il nécessite audiences:write, car il écrit des appartenances et non le contact, et le répéter ne change rien.
L'audience par défaut est toujours conservée, donc {'audienceIds': []} laisse le contact dans la seule audience par défaut. Il accepte jusqu'à 100 identifiants. Un identifiant qui ne désigne aucune audience de cet espace de travail donne un 404 audience_not_found et rien ne change, et une adresse qui n'est pas un contact donne un 404 contact_not_found.
Tout le monde sur la page Contacts
list_people liste les personnes que montre la page Contacts de l'application : les contacts enregistrés et chaque adresse vue dans le courrier, chacune avec saved, threads et lastAt. list ne donne que les contacts enregistrés. Les adresses vues dans le courrier ne viennent que si la clé détient aussi threads:read, et page['seen'] dit si c'est le cas. sort vaut recent, name ou threads, q cherche dans les noms, les adresses et les notes, et blocked=True garde les personnes que bloque la liste de blocage de l'espace de travail, règles sur des domaines entiers comprises. blockedBy nomme la règle sur chaque ligne.
from openemail import openemail page = openemail.contacts.list_people(sort='threads', limit=50) for person in page['items']: if not person['saved'] and (person['threads'] or 0) > 5: openemail.contacts.save(person['email']) blocked = openemail.contacts.list_all_people(blocked=True)list_all_people et iterate_people parcourent chaque page. Le curseur est opaque, renvoyez donc nextCursor tel qu'il est venu, avec les mêmes sort, q et blocked.
Enregistrer, supprimer et photos
save(email, {'name': ..., 'notes': ...}) correspond à Ajouter aux contacts et Garder dans les contacts : il enregistre une adresse qui n'est pas encore un contact, garde comme enregistrée à la main une adresse relevée lors d'un envoi, et ramène une adresse supprimée. delete correspond à Supprimer : il retire le contact enregistré et masque l'adresse, pour que l'éditeur ne l'enregistre plus, et il accepte aussi une adresse seulement vue dans le courrier. wasSaved dit de quel cas il s'agissait. delete_many en supprime jusqu'à 200 en un seul appel.
from pathlib import Path from openemail import openemail openemail.contacts.save('[email protected]', {'name': 'Grace Hopper'}) photo = Path('grace.jpg').read_bytes()contact = openemail.contacts.set_photo('[email protected]', photo, content_type='image/jpeg') openemail.contacts.remove_photo('[email protected]')openemail.contacts.delete_many(['[email protected]', '[email protected]'])set_photo envoie les octets de l'image tels quels : PNG, JPEG, WebP ou GIF jusqu'à 5 Mo, ajustés dans un carré de 512 pixels. Passez content_type=, car des octets ne portent pas de type propre : sans lui, le téléversement part en application/octet-stream, qui est refusé avec un 422 invalid_image. L'adresse doit d'abord être un contact enregistré.
Blocage
block(email) met l'adresse sur la liste de blocage de l'espace de travail pour que son courrier soit refusé, en retirant toute étiquette plus, et unblock(email) retire chaque règle qui la bloque. Les deux demandent settings:write, car ils modifient la liste de blocage et non le contact, et aucun n'exige que l'adresse soit un contact.
Quand unblock lève une règle sur un domaine entier, removed la liste avec list à blockedDomains, et tout le monde sur ce domaine est débloqué avec elle.
Conversations et activité
list_threads(email) parcourt page par page les fils que l'adresse a écrits ou qui lui ont été écrits, dans tous les dossiers, et list_all_threads et iterate_threads les parcourent entièrement. activity(email) renvoie les chiffres derrière l'onglet Activité d'un contact : reçus et envoyés par intervalle, fils qui attendent votre réponse, et temps de réponse médian dans chaque sens. Les deux demandent threads:read.
import time from openemail import openemail threads = openemail.contacts.list_threads('[email protected]', q='invoice') activity = openemail.contacts.activity( '[email protected]', minutes=30 * 24 * 60, grain='day', offset_minutes=time.localtime().tm_gmtoff // 60,) print(len(threads['items']), activity['totals']['waiting'])Référence
contacts.list()Référence complètecontacts.list_all()Référence complètecontacts.iterate()Référence complètecontacts.get()Référence complètecontacts.create()Référence complètecontacts.save()Référence complètecontacts.update()Référence complètecontacts.set_audiences()Référence complètecontacts.delete()Référence complètecontacts.delete_many()Référence complètecontacts.list_people()Référence complètecontacts.list_all_people()Référence complètecontacts.iterate_people()Référence complètecontacts.set_photo()Référence complètecontacts.remove_photo()Référence complètecontacts.block()Référence complètecontacts.unblock()Référence complètecontacts.list_threads()Référence complètecontacts.list_all_threads()Référence complètecontacts.iterate_threads()Référence complètecontacts.activity()Référence complète