From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp1 ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id mGkpJaxZRWBhQQAA0tVLHw (envelope-from ) for ; Sun, 07 Mar 2021 22:54:36 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp1 with LMTPS id qDDUIKxZRWC6dwAAbx9fmQ (envelope-from ) for ; Sun, 07 Mar 2021 22:54:36 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 95CEB25D4E for ; Sun, 7 Mar 2021 23:54:35 +0100 (CET) Received: from localhost ([::1]:54402 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lJ2IE-0001xo-19 for larch@yhetil.org; Sun, 07 Mar 2021 17:54:34 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:49140) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lJ2Hi-0001wG-SD for emacs-orgmode@gnu.org; Sun, 07 Mar 2021 17:54:02 -0500 Received: from stw1.rcdrun.com ([217.170.207.13]:56417) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lJ2Hg-0005nD-02 for emacs-orgmode@gnu.org; Sun, 07 Mar 2021 17:54:02 -0500 Received: from localhost ([::ffff:41.210.141.24]) (AUTH: PLAIN securesender, TLS: TLS1.2,256bits,ECDHE_RSA_AES_256_GCM_SHA384) by stw1.rcdrun.com with ESMTPSA id 000000000001E084.0000000060455984.000036E1; Sun, 07 Mar 2021 15:53:55 -0700 Date: Mon, 8 Mar 2021 01:51:32 +0300 From: Jean Louis To: dalanicolai Subject: Re: contact management in emacs Message-ID: Mail-Followup-To: dalanicolai , emacs-orgmode@gnu.org References: Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=_stw1.rcdrun.com-14049-1615157637-0001-2" Content-Disposition: inline In-Reply-To: User-Agent: Mutt/2.0 (3d08634) (2020-11-07) Received-SPF: pass client-ip=217.170.207.13; envelope-from=bugs@gnu.support; helo=stw1.rcdrun.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_FILL_THIS_FORM_SHORT=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: emacs-orgmode@gnu.org Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: "Emacs-orgmode" X-Migadu-Flow: FLOW_IN ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1615157675; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post; bh=S8ZLIx+r2jkRAXdS61QYMXKJuNFGjcPvxzrHOj36wZ8=; b=fFKes443WNJUcgFfGZeY3puGi5HxIePd6GVD3nmuXinHRhmWuuVXJ8kfmuDEWPBo0EhOFL TXVdSf0FS0FznAuFqzdItAqB4lLfs/XKZu7TfKUMQJcwz6M9rOUATPJkz5Ef5pWxrh6W7E F3n+79A9vq4/wBwzi9+1G2ACyKx9DvULduxidY14+o77FCkAHypPpgW6RNEA64FnGyW8j/ NggemzDbMZDFgEU1fHXio+JpWDcptBLXe31cSO/cZRMSDBJkNmivla+cEiwE+hhGq1FPjx M4rY+nvxg5TMo11DJABOw2QZ8buOiWenLA3DH/KZOa6qQmk6hgBV2Z+s7CPJmQ== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1615157675; a=rsa-sha256; cv=none; b=Js5mKYIhtKJLh7ljarz2GLS16qBUN8NwjExjbyUqgVyECFyOKsVogSJ8C3ihJukwfI52bz NRntzedxgFxUCfj7/41FajK0RaVyYRQ1ogm6kbjba/soDPKggyCWM2RmrkqxIVi18zT3X1 11hJ7Ylhx+2EKrMic6X9Mi5MxjGe8/Mw67ADOaStYlCD0aspP0RcUqaYNKC841nr9VKOKL RZ7TMvVEODzT3h7VHDTh9+X41UPUVjqS8cNwgHBNjF/inVZ5jo7mBrbGYm3WS7scHL19uM Q1tkDXFq01KEDWxGiIaAeWm/2vpMZrXixaBH/PxXndmE7X1wUf9VhZqnwBKsYw== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of emacs-orgmode-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=emacs-orgmode-bounces@gnu.org X-Migadu-Spam-Score: -0.88 Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of emacs-orgmode-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=emacs-orgmode-bounces@gnu.org X-Migadu-Queue-Id: 95CEB25D4E X-Spam-Score: -0.88 X-Migadu-Scanner: scn1.migadu.com X-TUID: sbipvhm8C3lP This is a MIME-formatted message. If you see this text it means that your E-mail software does not support MIME-formatted messages. --=_stw1.rcdrun.com-14049-1615157637-0001-2 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Content-Disposition: inline * dalanicolai [2021-02-27 23:53]: > I think all packages fulfill your requirements. So I would say it depends > on how many contacts you are managing. I have some experience with > org-contacts, and I find it very convenient and straightforward. It is also > very convenient to just use org-mode, i.e. a plain text file, for your > contacts. That may be convenient for friends or family, but is not a good idea if such a contact database is to enlarge due to marketing actions. People who collect leads and manage relations with many other people must have straight way to manage contacts, and similar to well known CRM systems such as SugarCRM or others. In fact contact management could be managed by external program and database accessed through Emacs. Though I do both with Emacs. And I like to access database from shell as I do not use only Emacs as editor. As the database is liberated from editor it allows access through any software or programming language. > Every contact is a headline and you can add any kind of property > or tag etc. you want. Also anniversaries get added to the Agenda. You can > very easily jump to the right contact, using imenu or swoop/swiper (I use > `SPC j i ` in Spacemacs. So if you have less than say 300 contacts (I have > really no clue about the number of contacts that will still work smoothly), > then depending on how die-hard you are, I would recommend to start with > org-contacs. More important is how fast are contacts coming into the database. If there are just 100 per year, then that will work well. But marketing action of 23 hours have provided me like 1700 contacts, so there would be no way that I ever keep up with text or hand work. That requires automated insertion of contacts into the database, and I use local database. Online lead capture is sent PGP encrypted by email and emails are automatically processed and leads entered into the local database. Placing contacts online is insecure IMHO, no matter what is advertised about it. > You can use org-vcard to import contacts, and org-vcard claims to > support exports too but I did not test that yet. Anyway, I think > you won't loose much time with setting up org-contacts and from then > you can slowly check out and study the other options. I am attaching `rcd-vcard.el` that uses PostgreSQL database and my schemas to export vCards that work nicely with Android/LineageOS/Replicant devices. Package alone will not work. Functions may be useful for some people to modify them as they wish. If somebody wish to really install my system, I will be helpful in private chat or email and guide person until it becomes functional. Jean --=_stw1.rcdrun.com-14049-1615157637-0001-2 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="rcd-vcard.el" ;;; rcd-vcard.el --- RCD vCard functions -*- lexical-binding: t; -*- ;; Copyright (C) 2016-2021 by Jean Louis ;; Author: Jean Louis ;; Version: 0.1 ;; Package-Requires: (rcd-utilities rcd-db-init rcd-db rcd-cf) ;; Keywords: ;; URL: https://gnu.support/gnu-emacs/packages/rcd-vcard.html ;; This file is not part of GNU Emacs. ;; This program is free software: you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as ;; published by the Free Software Foundation, either version 3 of the ;; License, or (at your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; These are the RCD vCard functions ;; ;; RCD is acronym for Reach, Connect, Deliver, my personal ;; principle and formula for Wealth. ;;; Change Log: ;;; Code: (require 'rcd-utilities) (require 'rcd-db-init) (require 'rcd-db) (require 'rcd-cf) (defvar *rcd-vcard-version* "2.1") (defvar *rcd-vcard-output* "~/tmp/rcd-vcards/") (defun rcd-vcard-jabber (xmpp) (if (rcd-string-not-empty-p xmpp) (format "X-JABBER:%s\nX-JABBER;WORK:%s\n" xmpp xmpp) "")) (defun rcd-vcard-tel (tel &optional type) (if (rcd-string-not-empty-p tel) (let* ((type (or type "CELL")) (type (upcase type))) (format "TEL;%s:%s\n" type tel)) "")) (defun rcd-vcard-address (address1 city1 zip1 state1 country1 address2 city2 zip2 state2 country2) (with-output-to-string (princ "ADR;DOM;HOME;:") (princ city1) (princ ";") (princ country1) (princ "\n"))) ;; TODO (defun rcd-vcard-phones (office mobile home other fax &optional other-2 other-3 other-4) (with-output-to-string (when office (princ (rcd-vcard-tel office "WORK"))) (when mobile (princ (rcd-vcard-tel mobile "CELL"))) (when home (princ (rcd-vcard-tel home "HOME"))) (when other (princ (rcd-vcard-tel other "OTHER"))) (when fax (princ (rcd-vcard-tel fax "FAX"))) (when other-2 (princ (rcd-vcard-tel other-2 "OTHER"))) (when other-3 (princ (rcd-vcard-tel other-3 "OTHER"))) (when other-3 (princ (rcd-vcard-tel other-3 "OTHER"))))) (defun rcd-vcard-title (title) (if (rcd-string-not-empty-p title) (format "TITLE:%s\n" title) "")) (defun rcd-vcard-organization (org &optional unit) (if (rcd-string-not-empty-p org) (let ((unit (or unit ""))) (format "ORG:%s;%s\n" org unit)) "")) ;; (defun rcd-vcard-note (note) ;; (if (rcd-string-not-empty-p note) ;; (format "NOTE:ENCODING=BASE64;:%s\n" (base64-encode-string note)) ;; "")) (defun rcd-vcard-note (id note) (with-output-to-string ;; (princ (format "NOTE;ENCODING=BIT8;:Contact ID %s; " id)) (princ (format "NOTE:Contact ID %s" id)) (if (rcd-string-not-empty-p note) (princ (format "%s\n" "")) ;; place note instead of "" ""))) (defun rcd-vcard-begin () (format "BEGIN:VCARD\nVERSION:%s\n" *rcd-vcard-version*)) (defun rcd-vcard-end () (format "END:VCARD\n")) (defun rcd-vcard-email (email &optional type) (if (rcd-string-not-empty-p email) (let* ((type (or type "HOME")) (type (upcase type))) (format "EMAIL;%s:%s\n" type email)) "")) (defun rcd-vcard-url (url) (if (rcd-string-not-empty-p url) (format "URL:%s\n" url) "")) (defun rcd-vcard-birthday (bday) (if (rcd-string-not-empty-p bday) (format "BDAY:%s\n" bday) "")) (defun rcd-vcard-formatted-name (fn) (if (rcd-string-not-empty-p fn) (format "FN:%s\n" fn) "")) (defun rcd-vcard-name (last &optional first middle prefix suffix) (if (rcd-string-not-empty-p last) (let ((first (or first "")) (middle (or middle "")) (prefix (or prefix "")) (suffix (or suffix ""))) (format "N;CHARSET=UTF-8:%s;%s;%s;%s;%s;\n" last first middle prefix suffix)) "")) (defun cf-contact-geo-location (id) (let* ((sql (format "SELECT locations_latitude, locations_longitude FROM locations WHERE locations_contacts = %s" id)) (geo (car (rcd-sql-list sql *cf*))) (latitude (car geo)) (longitude (cadr geo))) (if geo (format "geo:%s,%s" latitude longitude) nil))) (defun rcd-cf-contact-vcard-list (id) (let* ((hash (rcd-db-table-id-hash-values "people" id *cf*)) (prefix (gethash 'people_prefix hash)) (first (gethash 'people_firstname hash)) (middle (gethash 'people_middlenames hash)) (last (gethash 'people_lastname hash)) (suffix (gethash 'people_suffix hash)) (account (gethash 'people_account1 hash)) (company (gethash 'people_account2 hash)) (member (gethash 'people_account3 hash)) (title (gethash 'people_title hash)) (department (gethash 'people_department hash)) (birthday (gethash 'people_birthdate hash)) (office (gethash 'people_officephone hash)) (mobile (gethash 'people_mobilephone hash)) (home (gethash 'people_homephone hash)) (other (gethash 'people_otherphone hash)) (fax (gethash 'people_fax hash)) (email1 (gethash 'people_email1 hash)) (email2 (gethash 'people_email2 hash)) (email3 (gethash 'people_email3 hash)) (website (gethash 'people_website1 hash)) (blog (gethash 'people_website2 hash)) (address1 (gethash 'people_address1 hash)) (city1 (gethash 'people_city1 hash)) (zip1 (gethash 'people_zip1 hash)) (state1 (gethash 'people_state1 hash)) (country1 (gethash 'people_country1 hash)) (address2 (gethash 'people_address2 hash)) (city2 (gethash 'people_city2 hash)) (zip2 (gethash 'people_zip2 hash)) (state2 (gethash 'people_state2 hash)) (country2 (gethash 'people_country2 hash)) (note (gethash 'people_description hash)) (geo (cf-contact-geo-location id)) (geo (if geo (upcase geo) "")) (contact (list prefix first middle last suffix account company member title department birthday office mobile home other fax email1 email2 email3 website blog address1 city1 zip1 state1 country1 address2 city2 zip2 state2 country2 note geo))) (mapcar 'string-blank-nil contact))) (defun rcd-cf-contact-vcard (id) (let* ((contact (rcd-cf-contact-vcard-list id)) (full-name (cf-get-full-name id)) (vcard (rcd-vcard-begin)) (prefix (elt contact 0)) (first (elt contact 1)) (middle (elt contact 2)) (last (elt contact 3)) (suffix (elt contact 4)) (n (rcd-vcard-name last first middle prefix suffix)) (vcard (concat vcard n)) (fn (concat prefix " " first " " middle " " last " " suffix)) (fn (replace-regexp-in-string " +" " " fn)) (fn (rcd-vcard-formatted-name fn)) (vcard (concat vcard fn)) (account (elt contact 5)) (company (elt contact 6)) (member (elt contact 7)) (title (elt contact 8)) (department (elt contact 9)) (org (rcd-vcard-organization company department)) (vcard (concat vcard org)) (account-org (rcd-vcard-organization account "Account")) (vcard (concat vcard account-org)) (member-org (rcd-vcard-organization member "Member")) (vcard (concat vcard member-org)) (vcard (concat vcard (rcd-vcard-title title))) (birthday (elt contact 10)) (vcard (concat vcard (rcd-vcard-birthday birthday))) (office (elt contact 11)) (mobile (elt contact 12)) (home (elt contact 13)) (other (elt contact 14)) (fax (elt contact 15)) (phones (rcd-vcard-phones office mobile home other fax)) (vcard (concat vcard phones)) (email1 (elt contact 16)) (email2 (elt contact 17)) (email3 (elt contact 18)) (vcard (concat vcard (rcd-vcard-email email1))) (vcard (concat vcard (rcd-vcard-email email2))) (vcard (concat vcard (rcd-vcard-email email3))) (website (elt contact 19)) (vcard (concat vcard (rcd-vcard-url website))) (blog (elt contact 20)) (vcard (concat vcard (rcd-vcard-url blog))) (address1 (elt contact 21)) (city1 (elt contact 22)) (zip1 (elt contact 23)) (state1 (elt contact 24)) (country1 (elt contact 25)) (address2 (elt contact 26)) (city2 (elt contact 27)) (zip2 (elt contact 28)) (state2 (elt contact 29)) (country2 (elt contact 30)) (address (rcd-vcard-address address1 city1 zip1 state1 country1 address2 city2 zip2 state2 country2)) (vcard (concat vcard address)) (note (elt contact 31)) (note (rcd-vcard-note id note)) (vcard (concat vcard note)) (geo (elt contact 32)) (geo (if geo (concat geo "\n") "")) (vcard (concat vcard geo)) ;;(vcard (concat vcard note)) (vcard (concat vcard (rcd-vcard-end)))) vcard)) (defun rcd-vcard-mobile-1 () "Exports all vCards for mobile phone #1" (interactive) (make-directory *rcd-vcard-output* t) (let* ((ids (rcd-sql "SELECT addressbookentries_people FROM addressbookentries" *cf*))) (string-to-file-force (with-output-to-string (dolist (id ids) (princ (rcd-cf-contact-vcard id)))) (concat *rcd-vcard-output* "rcd-people.vcf")))) (defun cf-contact-vcard-export (id) "Export vCard for contact ID" (let ((vcard (rcd-cf-contact-vcard id)) (file (format "%s%08d.vcf" *rcd-vcard-output* id))) (string-to-file-force vcard file) (message (concat "vCard exported to: " file)))) (provide 'rcd-vcard) ;;; rcd-vcard.el ends here --=_stw1.rcdrun.com-14049-1615157637-0001-2--