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
page = client.contacts.list(limit: 100)contact = client.contacts.get("[email protected]") saved = client.contacts.create( email: "[email protected]", name: "Grace Hopper", notes: "Met at the compiler workshop") client.contacts.update("[email protected]", notes: nil)client.contacts.set_audiences("[email protected]", audienceIds: ["aud_4c1b8e2a7d9f05c36b4e8a71"])client.contacts.delete("[email protected]") puts page.items.size, page.has_more?, contact[:source], contact[:lastSeenAt], saved[:source]list devuelve primero los contactos 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 audiences.add_contact, que se trata en la página Audiencias. set_audiences indica exactamente en qué listas está un contacto, en una sola llamada.
Las direcciones se almacenan en minúsculas y la gema codifica la que pasas, así que [email protected] llega a la fila correcta. Una dirección nil o vacía lanza ArgumentError antes de enviar nada. 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
limitInteger- Cuántos contactos devolver por página: un número entero de 1 a 200, con 50 por defecto. Se convierte de tipo, así que una String como `"100"` leída de una cadena de consulta es válida, y un valor fuera del rango es un 422 en lugar de un valor recortado.
cursorString- El `next_cursor` 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`, lanzado como `OpenEmail::InvalidRequestError`, lo que significa que tu estado de paginación está obsoleto y el recorrido debe reiniciarse sin cursor.
sourceString- `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.
qString- 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: un contacto
contacts.list devuelve una OpenEmail::Page, así que las filas están en page.items y el recorrido sigue page.next_cursor mientras page.has_more? sea true. list_all devuelve todas las filas como un solo Array, e iterate las entrega de una en una. get, create, update, save y set_audiences devuelven cada uno un contacto como Hash con claves Symbol, la misma fila más audiences. La libreta de direcciones no tiene límite, y por eso esta ruta pagina en lugar de devolver un Array que se detuvo en silencio en 200.
objectString- Siempre la cadena `contact`, tanto en las filas de la lista como en `get`.
emailString- 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.
nameString or nil- El nombre visible, o nil 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.
sourceString- `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í. Trata el valor como una String abierta, porque la columna es texto libre con `manual` por defecto.
notesString or nil- Texto libre que alguien escribió sobre esta persona, en la aplicación o mediante `update`, nunca generado. Es nil cuando nadie ha escrito nada, y `notes: nil` en `update` lo borra.
lastSeenAtString or nil- Una cadena ISO 8601 en UTC, actualizada 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 nil 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.
audiencesArray<Hash>- Solo en `get`, `create`, `update`, `save` y `set_audiences`, nunca en las filas de la lista. Todas las audiencias a las que pertenece el contacto, incluida la audiencia por defecto, como un Hash con `id`, `name` y `builtin`. `builtin` es `default` en la audiencia a la que pertenecen todos los contactos y nil en una que alguien creó, así que ramifica según ese campo y no según el nombre, que cualquiera puede cambiar.
photoUrlString or nil- Dónde se sirve la foto del contacto, o nil 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 contacto tras el cambio, con sus audiences. Necesita audiences:write, porque escribe pertenencias y no el contacto, y repetirla no cambia nada, así que la gema la reintenta tras un fallo de red.
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. Ambos lanzan OpenEmail::NotFoundError.
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, y devuelve una OpenEmail::PeoplePage, que añade seen a items, has_more? y next_cursor. 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, y OpenEmail::PEOPLE_SORTS los nombra. 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.
page = client.contacts.list_people(sort: "threads", limit: 50) page.items.each do |person| client.contacts.save(person[:email]) if !person[:saved] && person[:threads].to_i > 5end blocked = client.contacts.list_all_people(blocked: true)puts page.seen, blocked.sizelist_all_people devuelve todas las páginas como un solo Array, e iterate_people pasa cada persona a un bloque, o devuelve un Enumerator sin bloque. Ninguno de los dos informa de seen, así que lee una página con list_people para saberlo. El cursor es opaco, así que devuelve next_cursor como cursor: exactamente como llegó, con los mismos sort:, q: y blocked:.
Guardar, eliminar y fotos
save(email), con name: y notes: opcionales, 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 redactor no la vuelva a registrar, y también acepta una dirección solo vista en el correo. wasSaved, en el Hash que devuelve, dice cuál de los dos casos era. delete_many elimina hasta 200 en una sola llamada.
client.contacts.save("[email protected]", name: "Grace Hopper") contact = client.contacts.set_photo("[email protected]", File.binread("photo.jpg"), content_type: "image/jpeg")puts contact[:photoUrl] client.contacts.set_photo("[email protected]", Pathname("photo.png")) client.contacts.remove_photo("[email protected]")client.contacts.delete_many(["[email protected]", "[email protected]"])set_photo envía los bytes de la imagen tal cual: PNG, JPEG, WebP o GIF de hasta 5 MB, ajustados a un cuadrado de 512 píxeles. Los bytes son una String binaria, un IO o un Pathname. Pasa content_type:, o bytes que lleven su propio tipo: un objeto que responda a content_type, como un archivo subido en Rails, o un File o un Pathname cuyo nombre termine en .png, .jpg, .jpeg, .webp o .gif. Sin tipo, los bytes van como application/octet-stream, que el servidor rechaza con un 422 invalid_image. OpenEmail::CONTACT_PHOTO_TYPES nombra los cuatro tipos. 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. OpenEmail::CONTACT_BLOCK_LISTS nombra las dos listas.
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.
threads = client.contacts.list_threads("[email protected]", q: "invoice") activity = client.contacts.activity( "[email protected]", minutes: 30 * 24 * 60, grain: "day", offset_minutes: Time.now.utc_offset / 60) puts threads.items.size, activity.dig(:totals, :waiting)activity acepta argumentos nombrados en snake_case. minutes: fija la ventana, que es de 90 días si se omite. grain: fija el ancho de cada intervalo: minute, hour o day. offset_minutes: fija los minutos al este de UTC en los que se cortan los días. Time.now.utc_offset / 60 es el desfase local, y la gema lo envía como el offsetMinutes de la API.