Contactos
`contacts.list`, `get`, `create`, `save`, `update`, `set_audiences`, `delete`, `delete_many`, `list_people`, `set_photo`, `remove_photo`, `block`, `unblock`, `list_threads` y `activity`.
Todos los métodos
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'])Primero los vistos más recientemente, y al final los contactos a los que nunca se ha escrito. source es auto cuando la fila se escribió porque un miembro envió un mensaje a esa dirección desde el redactor de la aplicación, lo que es una afirmación sustancialmente distinta de que alguien la haya guardado. El correo que llega desde una dirección no escribe nada, y un envío a través de esta API tampoco.
La libreta pertenece al espacio de trabajo y no a una persona, así que un contacto guardado por cualquier miembro es el contacto que ven todos los miembros y todas las claves. create escribe source como manual y coloca el contacto en la audiencia por defecto en el momento de escribirlo. Nombra tus propias listas en audienceIds para unirlo a ellas en la misma llamada, lo que además requiere audiences:write, o añade el contacto más tarde con openemail.audiences.add_contact. set_audiences indica exactamente en qué listas está un contacto, en una sola llamada.
Las direcciones se almacenan en minúsculas y el cliente codifica la que pasas, así que [email protected] llega a la fila correcta. La dirección es la identidad, de modo que update no puede cambiarla: mover un contacto es un delete y un create.
Parámetros: contacts.list
limitint- Cuántos contactos devolver por página: un integer de 1 a 200, con 50 por defecto. Se convierte de tipo, así que `'100'` procedente de una cadena de consulta es válido, y un valor fuera del rango es un 422 en lugar de un valor recortado.
cursorstr- El `nextCursor` de la página anterior. Nunca construyas uno a mano: un cursor que nombra a un contacto que ya no existe es un 400 `invalid_cursor`, lo que significa que tu estado de paginación está obsoleto y el recorrido debe reiniciarse sin cursor.
sourceContactSource- `'manual'` para los contactos que alguien guardó a propósito, `'auto'` para los que registró el redactor de la aplicación. Omítelo para obtener toda la libreta.
qstr- Busca en el nombre y la dirección, hasta 200 caracteres. Si nada coincide exactamente en la primera página, se devuelven grafías cercanas, y las páginas siguientes siguen buscando del mismo modo.
Respuesta: ContactResource
contacts.list devuelve un Page[ContactResource], así que las filas están en page['items'] y el recorrido sigue page['nextCursor'] mientras page['hasMore'] sea True, cosa que list_all e iterate hacen por ti. get, create, save, update, set_audiences, set_photo y remove_photo devuelven cada uno un ContactDetailResource, la misma fila más audiences. La libreta de direcciones no tiene límite, y por eso esta ruta pagina en lugar de devolver una lista que se detuvo en silencio en 200.
objectLiteral['contact']- Siempre la cadena `contact`, tanto en las filas de la lista como en `get`.
emailstr- La dirección, pasada a minúsculas al escribirla para que `[email protected]` y `[email protected]` sean un único contacto, y la clave que acepta todo método de contacts, ya que no se expone ningún id de contacto. Las filas pertenecen al espacio de trabajo y no al miembro o a la clave que las escribió, así que todos los miembros y todas las claves del espacio de trabajo leen y escriben una sola libreta de direcciones.
namestr | None- `None` cuando nunca se ha registrado un nombre para la dirección. Una escritura automática solo lleva uno cuando la cabecera aportó algo distinto de la propia dirección, y nunca puede sobrescribir un nombre que escribió el usuario.
sourceContactSource | str- `auto` significa que la fila se escribió porque el usuario envió correo a esa dirección; `manual` significa que alguien la introdujo a mano, una afirmación sustancialmente distinta, y un upsert nunca degrada `manual` de vuelta a `auto`. El correo que llega desde una dirección no escribe ninguna fila, deliberadamente, así que alguien que solo te ha escrito a ti no está aquí; la unión se mantiene abierta porque la columna es texto libre con `manual` por defecto.
notesstr | None- Texto libre que alguien escribió sobre esta persona, en la aplicación o mediante `update`, nunca generado. Es `None` cuando nadie ha escrito nada, y un `None` explícito en `update` lo borra.
lastSeenAtstr | None- ISO-8601 UTC, actualizado cada vez que un miembro envía a esa dirección desde el redactor de la aplicación, no cuando llega correo desde ella, que no escribe nada. Es `None` en un contacto guardado con `create` al que nunca se ha escrito, y esos quedan al final del orden descendente por `lastSeenAt` que devuelve esta ruta.
audienceslist[ContactAudienceResource]- Solo en `get`, `create`, `save`, `update`, `set_audiences`, `set_photo` y `remove_photo`, nunca en las filas de la lista. Todas las audiencias a las que pertenece el contacto, como un diccionario con `id`, `name` y `builtin`, incluida la audiencia por defecto. `builtin` es `default` en la audiencia a la que pertenecen todos los contactos y `None` en una que alguien creó, así que decide según ese campo y no según el nombre, que cualquiera puede cambiar.
photoUrlstr | None- Dónde se sirve la foto del contacto, o `None` cuando el contacto no tiene. `set_photo` la pone y cada subida recibe una URL nueva.
Definir las audiencias de un contacto
set_audiences(email, {'audienceIds': [...]}) indica exactamente en qué audiencias está un contacto, en una sola solicitud. El contacto se une a cada audiencia indicada en la que aún no está y sale de todas las demás, y la llamada devuelve el ContactDetailResource tras el cambio. Necesita audiences:write, porque escribe pertenencias y no el contacto, y repetirla no cambia nada.
La audiencia por defecto se conserva siempre, así que {'audienceIds': []} deja el contacto solo en la audiencia por defecto. Admite hasta 100 ids. Un id que no nombra ninguna audiencia de este espacio de trabajo es un 404 audience_not_found y no cambia nada, y una dirección que no es un contacto es un 404 contact_not_found.
Todos los de la página de Contactos
list_people lista a las personas que muestra la página de Contactos de la app: los contactos guardados y cada dirección vista en el correo, cada una con saved, threads y lastAt. list son solo los contactos guardados. Las direcciones vistas en el correo solo llegan cuando la clave también tiene threads:read, y page['seen'] dice si llegaron. sort es recent, name o threads, q busca en nombres, direcciones y notas, y blocked=True se queda con las personas que bloquea la lista de bloqueo del espacio de trabajo, incluidas las reglas de dominio entero. blockedBy nombra la regla en cada fila.
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 e iterate_people recorren todas las páginas. El cursor es opaco, así que devuelve nextCursor tal como llegó, con los mismos sort, q y blocked.
Guardar, eliminar y fotos
save(email, {'name': ..., 'notes': ...}) es Añadir a contactos y Mantener en contactos: guarda una dirección que aún no es un contacto, mantiene como guardada a mano una registrada desde un envío y recupera una eliminada. delete es Eliminar: quita el contacto guardado y oculta la dirección, para que el editor no la vuelva a registrar, y también acepta una dirección solo vista en el correo. wasSaved dice cuál de los dos casos era. delete_many elimina hasta 200 en una sola llamada.
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 envía los bytes de la imagen tal cual: PNG, JPEG, WebP o GIF hasta 5 MB, ajustados a un cuadrado de 512 píxeles. Pasa content_type=, porque los bytes no llevan un tipo propio: sin él, la subida va como application/octet-stream, que se rechaza con un 422 invalid_image. La dirección tiene que ser antes un contacto guardado.
Bloqueo
block(email) pone la dirección en la lista de bloqueo del espacio de trabajo para que su correo se rechace, quitando cualquier etiqueta con más, y unblock(email) quita cada regla que la bloquea. Los dos necesitan settings:write, porque cambian la lista de bloqueo y no el contacto, y ninguno necesita que la dirección sea un contacto.
Cuando unblock levanta una regla de dominio entero, removed la lista con list en blockedDomains, y todos los de ese dominio quedan desbloqueados con ella.
Conversaciones y actividad
list_threads(email) recorre por páginas los hilos que la dirección escribió o en los que se le escribió, en todas las carpetas, y list_all_threads e iterate_threads los recorren enteros. activity(email) devuelve las cifras de la pestaña Actividad de un contacto: recibidos y enviados por intervalo, hilos que esperan tu respuesta y la mediana del tiempo de respuesta en cada sentido. Los dos necesitan 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'])Referencia
contacts.list()Referencia completacontacts.list_all()Referencia completacontacts.iterate()Referencia completacontacts.get()Referencia completacontacts.create()Referencia completacontacts.save()Referencia completacontacts.update()Referencia completacontacts.set_audiences()Referencia completacontacts.delete()Referencia completacontacts.delete_many()Referencia completacontacts.list_people()Referencia completacontacts.list_all_people()Referencia completacontacts.iterate_people()Referencia completacontacts.set_photo()Referencia completacontacts.remove_photo()Referencia completacontacts.block()Referencia completacontacts.unblock()Referencia completacontacts.list_threads()Referencia completacontacts.list_all_threads()Referencia completacontacts.iterate_threads()Referencia completacontacts.activity()Referencia completa