Kontakte
`contacts.list`, `get`, `create`, `save`, `update`, `set_audiences`, `delete`, `delete_many`, `list_people`, `set_photo`, `remove_photo`, `block`, `unblock`, `list_threads` und `activity`.
Jede Methode
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'])Zuletzt gesehene zuerst, Kontakte ohne je versendete Mail zuletzt. source ist auto, wenn die Zeile geschrieben wurde, weil ein Mitglied dieser Adresse eine Nachricht aus dem Composer der App gesendet hat, was eine inhaltlich andere Aussage ist als das bewusste Speichern durch jemanden. Eingehende Mail von einer Adresse schreibt nichts, ein Versand über diese API ebenso wenig.
Das Adressbuch gehört dem Workspace und nicht einer einzelnen Person, ein von irgendeinem Mitglied gespeicherter Kontakt ist daher der Kontakt, den jedes Mitglied und jeder Schlüssel sieht. create schreibt source als manual und legt den Kontakt beim Schreiben in die Standard-Audience. Nennen Sie eigene Listen in audienceIds, um sie im selben Aufruf zuzuordnen, was zusätzlich audiences:write erfordert, oder fügen Sie den Kontakt später mit openemail.audiences.add_contact hinzu. set_audiences legt in einem Aufruf genau fest, in welchen Listen ein Kontakt ist.
Adressen werden in Kleinbuchstaben gespeichert und der Client kodiert die übergebene Adresse, [email protected] erreicht daher die richtige Zeile. Die Adresse ist die Identität, update kann sie daher nicht ändern: Einen Kontakt zu verschieben heißt delete und create.
Parameter: contacts.list
limitint- Wie viele Kontakte pro Seite zurückgegeben werden: ein integer von 1 bis 200, Standard 50. Der Wert wird konvertiert, `'100'` aus einem Query-String ist also in Ordnung, und ein Wert außerhalb des Bereichs ergibt ein 422 statt eines begrenzten Werts.
cursorstr- Der `nextCursor` der vorherigen Seite. Bauen Sie nie selbst einen: Ein cursor, der einen nicht mehr existierenden Kontakt nennt, ergibt ein 400 `invalid_cursor`, was bedeutet, dass Ihr Paging-Zustand veraltet ist und der Durchlauf ohne cursor neu beginnen sollte.
sourceContactSource- `'manual'` für die Kontakte, die jemand bewusst gespeichert hat, `'auto'` für die, die der Composer der App aufgezeichnet hat. Lassen Sie es weg, um das gesamte Adressbuch zu erhalten.
qstr- Durchsucht Name und Adresse, bis zu 200 Zeichen. Passt auf der ersten Seite nichts genau, kommen stattdessen ähnliche Schreibweisen zurück, und die folgenden Seiten suchen auf dieselbe Weise weiter.
Antwort: ContactResource
contacts.list gibt eine Page[ContactResource] zurück, die Zeilen stehen also in page['items'], und der Durchlauf folgt page['nextCursor'], solange page['hasMore'] True ist, was list_all und iterate für Sie erledigen. get, create, save, update, set_audiences, set_photo und remove_photo geben jeweils eine ContactDetailResource zurück, dieselbe Zeile plus audiences. Das Adressbuch ist unbegrenzt, deshalb paginiert diese Route, statt eine Liste zurückzugeben, die stillschweigend bei 200 aufhört.
objectLiteral['contact']- Immer der String `contact`, auf den Listenzeilen ebenso wie bei `get`.
emailstr- Die Adresse, beim Schreiben in Kleinbuchstaben umgewandelt, sodass `[email protected]` und `[email protected]` ein Kontakt sind, und zugleich der Schlüssel, den jede contacts-Methode entgegennimmt, da keine Kontakt-id nach außen gegeben wird. Zeilen gehören dem Workspace und nicht dem Mitglied oder dem Schlüssel, der sie geschrieben hat, jedes Mitglied und jeder Schlüssel im Workspace liest und schreibt daher ein einziges Adressbuch.
namestr | None- `None`, wenn für die Adresse nie ein Name erfasst wurde. Ein automatischer Schreibvorgang trägt nur dann einen ein, wenn der Header etwas anderes als die Adresse selbst geliefert hat, und er kann niemals einen vom Benutzer eingegebenen Namen überschreiben.
sourceContactSource | str- `auto` bedeutet, dass die Zeile geschrieben wurde, weil der Benutzer Mail an diese Adresse gesendet hat; `manual` bedeutet, dass jemand sie von Hand eingetragen hat, eine inhaltlich andere Aussage, und ein Upsert stuft `manual` nie wieder auf `auto` herab. Eingehende Mail von einer Adresse schreibt bewusst gar keine Zeile, wer Ihnen also nur geschrieben hat, steht hier nicht; die Union bleibt offen, weil die Spalte Freitext mit Standardwert `manual` ist.
notesstr | None- Freitext, den jemand über diese Person geschrieben hat, in der App oder über `update`, nie generiert. `None`, wenn niemand etwas geschrieben hat, und ein explizites `None` bei `update` löscht ihn.
lastSeenAtstr | None- ISO-8601 UTC, wird jedes Mal aktualisiert, wenn ein Mitglied aus dem Composer der App an diese Adresse sendet, nicht wenn von ihr Mail eintrifft, was nichts schreibt. `None` bei einem über `create` gespeicherten Kontakt, an den nie gesendet wurde, und diese stehen in der absteigenden `lastSeenAt`-Sortierung dieser Route am Ende.
audienceslist[ContactAudienceResource]- Nur bei `get`, `create`, `save`, `update`, `set_audiences`, `set_photo` und `remove_photo`, nie bei Listenzeilen. Jede Audience, in der der Kontakt ist, als dict mit `id`, `name` und `builtin`, die Standard-Audience eingeschlossen. `builtin` ist `default` bei der Audience, zu der jeder Kontakt gehört, und `None` bei einer, die jemand angelegt hat; verzweigen Sie also danach und nicht nach dem Namen, den jeder ändern kann.
photoUrlstr | None- Wo das Kontaktfoto ausgeliefert wird, oder `None`, wenn der Kontakt keins hat. `set_photo` setzt es, und jeder Upload bekommt eine neue URL.
Die Audiences eines Kontakts festlegen
set_audiences(email, {'audienceIds': [...]}) legt in einer Anfrage genau fest, in welchen Audiences ein Kontakt ist. Der Kontakt tritt jeder genannten Audience bei, in der er noch nicht ist, und verlässt jede andere, und der Aufruf gibt die ContactDetailResource nach der Änderung zurück. Er erfordert audiences:write, weil er Mitgliedschaften schreibt und nicht den Kontakt, und eine Wiederholung ändert nichts.
Die Standard-Audience bleibt immer erhalten, {'audienceIds': []} lässt den Kontakt also nur in der Standard-Audience. Es nimmt bis zu 100 IDs. Eine ID, die keine Audience in diesem Workspace bezeichnet, ergibt ein 404 audience_not_found, und nichts ändert sich; eine Adresse, die kein Kontakt ist, ergibt ein 404 contact_not_found.
Alle auf der Kontaktseite
list_people listet die Personen, die die Kontaktseite der App zeigt: die gespeicherten Kontakte und jede Adresse aus den Mails, jeweils mit saved, threads und lastAt. list sind nur die gespeicherten Kontakte. Die Adressen aus den Mails kommen nur, wenn der Schlüssel auch threads:read hat, und page['seen'] sagt, ob sie gekommen sind. sort ist recent, name oder threads, q durchsucht Namen, Adressen und Notizen, und blocked=True behält die Personen, die die Blockliste des Workspace blockiert, Regeln für ganze Domains eingeschlossen. blockedBy nennt die Regel in jeder Zeile.
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 und iterate_people gehen jede Seite durch. Der Cursor ist undurchsichtig, gib nextCursor also so zurück, wie er kam, mit denselben sort, q und blocked.
Speichern, Löschen und Fotos
save(email, {'name': ..., 'notes': ...}) ist Zu Kontakten hinzufügen und In Kontakten behalten: Es speichert eine Adresse, die noch kein Kontakt ist, behält eine aus einem Versand erfasste als von Hand gespeichert und holt eine gelöschte zurück. delete ist Löschen: Es entfernt den gespeicherten Kontakt und blendet die Adresse aus, damit der Editor sie nicht wieder erfasst, und nimmt auch eine Adresse, die nur in Mails vorkam. wasSaved sagt, was davon es war. delete_many löscht bis zu 200 in einem Aufruf.
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 sendet die Bildbytes so, wie sie sind: PNG, JPEG, WebP oder GIF bis 5 MB, eingepasst in ein Quadrat von 512 Pixeln. Übergeben Sie content_type=, denn Bytes tragen keinen eigenen Typ: Ohne ihn geht der Upload als application/octet-stream hinaus, was mit einem 422 invalid_image abgelehnt wird. Die Adresse muss zuerst ein gespeicherter Kontakt sein.
Blockieren
block(email) setzt die Adresse auf die Blockliste des Workspace, sodass Mails von ihr abgewiesen werden, und lässt ein Plus-Tag weg, und unblock(email) nimmt jede Regel ab, die sie blockiert. Beide brauchen settings:write, weil sie die Blockliste ändern und nicht den Kontakt, und bei keinem muss die Adresse ein Kontakt sein.
Hebt unblock eine Regel für eine ganze Domain auf, listet removed sie mit list gleich blockedDomains, und die Blockierung aller bei dieser Domain wird mit ihr aufgehoben.
Unterhaltungen und Aktivität
list_threads(email) blättert durch die Threads, die die Adresse geschrieben hat oder die an sie gingen, in jedem Ordner, und list_all_threads und iterate_threads gehen sie durch. activity(email) liefert die Zahlen hinter dem Tab Aktivität eines Kontakts: empfangen und gesendet pro Abschnitt, Threads, die auf deine Antwort warten, und die mittlere Antwortzeit in beide Richtungen. Beide brauchen 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'])Referenz
contacts.list()Vollständige Referenzcontacts.list_all()Vollständige Referenzcontacts.iterate()Vollständige Referenzcontacts.get()Vollständige Referenzcontacts.create()Vollständige Referenzcontacts.save()Vollständige Referenzcontacts.update()Vollständige Referenzcontacts.set_audiences()Vollständige Referenzcontacts.delete()Vollständige Referenzcontacts.delete_many()Vollständige Referenzcontacts.list_people()Vollständige Referenzcontacts.list_all_people()Vollständige Referenzcontacts.iterate_people()Vollständige Referenzcontacts.set_photo()Vollständige Referenzcontacts.remove_photo()Vollständige Referenzcontacts.block()Vollständige Referenzcontacts.unblock()Vollständige Referenzcontacts.list_threads()Vollständige Referenzcontacts.list_all_threads()Vollständige Referenzcontacts.iterate_threads()Vollständige Referenzcontacts.activity()Vollständige Referenz