1 /* GNU Mailutils -- a suite of utilities for electronic mail
2    Copyright (C) 1999-2021 Free Software Foundation, Inc.
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 3 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General
15    Public License along with this library.  If not, see
16    <http://www.gnu.org/licenses/>. */
17 
18 #if HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <sys/types.h>
26 #include <stdio.h>
27 #include <mailutils/types.h>
28 #include <mailutils/address.h>
29 #include <mailutils/mu_auth.h>
30 #include <mailutils/util.h>
31 #include <mailutils/parse822.h>
32 #include <mailutils/errno.h>
33 
34 /*
35  * Functions used to convert unix mailbox/user names into RFC822 addr-specs.
36  */
37 
38 static char *mu_user_email = 0;
39 
40 int
mu_set_user_email(const char * candidate)41 mu_set_user_email (const char *candidate)
42 {
43   int err = 0;
44   mu_address_t addr = NULL;
45   size_t emailno = 0;
46   char *email = NULL;
47   const char *domain = NULL;
48 
49   if (!candidate)
50     {
51       free (mu_user_email);
52       mu_user_email = NULL;
53       return 0;
54     }
55 
56   if ((err = mu_address_create (&addr, candidate)) != 0)
57     return err;
58 
59   if ((err = mu_address_get_email_count (addr, &emailno)) != 0)
60     goto cleanup;
61 
62   if (emailno != 1)
63     {
64       errno = EINVAL;
65       goto cleanup;
66     }
67 
68   if ((err = mu_address_aget_email (addr, 1, &email)) != 0)
69     goto cleanup;
70   else if (email == NULL)
71     {
72       err = MU_ERR_NOENT;
73       goto cleanup;
74     }
75 
76   free (mu_user_email);
77 
78   mu_user_email = email;
79 
80   if ((err = mu_address_sget_domain (addr, 1, &domain)) != 0)
81     goto cleanup;
82   else if (domain == NULL)
83     {
84       err = MU_ERR_NOENT;
85       goto cleanup;
86     }
87   mu_set_user_email_domain (domain);
88 
89 cleanup:
90   mu_address_destroy (&addr);
91 
92   return err;
93 }
94 
95 static char *mu_user_email_domain = 0;
96 
97 int
mu_set_user_email_domain(const char * domain)98 mu_set_user_email_domain (const char *domain)
99 {
100   char *d;
101 
102   if (domain)
103     {
104       d = strdup (domain);
105 
106       if (!d)
107 	return ENOMEM;
108     }
109   else
110     d = NULL;
111 
112   if (mu_user_email_domain)
113     free (mu_user_email_domain);
114 
115   mu_user_email_domain = d;
116 
117   return 0;
118 }
119 
120 /* FIXME: must be called _sget_ */
121 int
mu_get_user_email_domain(const char ** domain)122 mu_get_user_email_domain (const char **domain)
123 {
124   int err = 0;
125 
126   if (!mu_user_email_domain)
127     {
128       if ((err = mu_get_host_name (&mu_user_email_domain)))
129 	return err;
130     }
131 
132   *domain = mu_user_email_domain;
133 
134   return 0;
135 }
136 
137 int
mu_aget_user_email_domain(char ** pdomain)138 mu_aget_user_email_domain (char **pdomain)
139 {
140   const char *domain;
141   int status = mu_get_user_email_domain (&domain);
142   if (status)
143     return status;
144   if (domain == NULL)
145     *pdomain = NULL;
146   else
147     {
148       *pdomain = strdup (domain);
149       if (*pdomain == NULL)
150 	return ENOMEM;
151     }
152   return 0;
153 }
154 
155 /* Note: allocates memory */
156 char *
mu_get_user_email(const char * name)157 mu_get_user_email (const char *name)
158 {
159   int status = 0;
160   char *localpart = NULL;
161   const char *domainpart = NULL;
162   char *email = NULL;
163   char *tmpname = NULL;
164 
165   if (!name && mu_user_email)
166     {
167       email = strdup (mu_user_email);
168       if (!email)
169 	errno = ENOMEM;
170       return email;
171     }
172 
173   if (!name)
174     {
175       struct mu_auth_data *auth = mu_get_auth_by_uid (geteuid ());
176       if (!auth)
177 	{
178 	  errno = EINVAL;
179 	  return NULL;
180 	}
181       name = tmpname = strdup(auth->name);
182       if (auth)
183 	mu_auth_data_free (auth);
184       if (!name)
185         {
186           errno = ENOMEM;
187           return NULL;
188         }
189     }
190 
191   status = mu_get_user_email_domain (&domainpart);
192 
193   if (status)
194     {
195       free(tmpname);
196       errno = status;
197       return NULL;
198     }
199 
200   if ((status = mu_parse822_quote_local_part (&localpart, name)))
201     {
202       free(tmpname);
203       errno = status;
204       return NULL;
205     }
206 
207 
208   email = malloc (strlen (localpart) + 1
209 		  + strlen (domainpart) + 1);
210   if (!email)
211     errno = ENOMEM;
212   else
213     sprintf (email, "%s@%s", localpart, domainpart);
214 
215   free(tmpname);
216   free (localpart);
217 
218   return email;
219 }
220