1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.email.policy;
18 
19 import android.os.Bundle;
20 
21 /**
22  * This sample is the framework that can be used to build EmailPolicy packages for inclusion
23  * on specific devices.  This sample is intended for use by OEMs or other creators of system
24  * images.
25  *
26  * When this package is built and included in a system image, the Email application will detect
27  * it (using reflection) and will make calls to the getPolicy() method at certain times.  This
28  * can be used to provide local customization of the Email application.
29  *
30  * Do not change the package, class name, or method name - these must match the names used in
31  * this sample code or the Email application will not find the helper.
32  *
33  * Three customization points are provided:
34  *
35  *   * Alternate strings for Exchange/ActiveSync UI
36  *   * Insertion of device-specific text into IMAP ID commands
37  *   * Device- or Carrier- specific account presets
38  *
39  * Each policy request may contain one or more parameters;  These are supplied as keyed entries
40  * in the "arguments" bundle.  If there is a single argument, it will typically use the same key
41  * as the policy name.  If there are multiple arguments, they keys are provided and called out.
42  *
43  * In all cases, getPolicy() should return a bundle.  For default behavior, or for any unknown
44  * policy, simply return Bundle.EMPTY.
45  *
46  * To return actual data, create a new bundle and place result values in it.  If there is a single
47  * return value, this value is placed in the return bundle using the same key as the request.
48  * If there are multiple return values, keys will be provided for them as well.
49  *
50  * Future versions of the Email application may access additional customization points.  If
51  * the call to getPolicy() is made with an unknown or unexpected policy keys, or the expected
52  * argument values cannot be found, the method should Bundle.EMPTY.
53  */
54 public class EmailPolicy {
55 
56     /**
57      * This policy request configures the UI to conform to various Exchange/ActiveSync
58      * license requirements.  In the default configuration, the UI will refer to this protocol as
59      * "Exchange", while in the alternate configuration, the UI will refer to it as
60      * "Exchange ActiveSync" or "Microsoft Exchange ActiveSync".
61      *
62      * For the default behavior, return the empty bundle.
63      * For the alternate behavior, return a bundle containing a single entry with a key of
64      * USE_ALTERNATE_EXCHANGE_STRINGS and a value of "true".
65      */
66     private static final String USE_ALTERNATE_EXCHANGE_STRINGS = "useAlternateExchangeStrings";
67 
68     /**
69      * This policy request allows you to insert field/value pairs into the IMAP ID command, which
70      * is sent to an IMAP server on each connection.
71      *
72      * The following arguments are provided:
73      *   * GET_IMAP_ID_USER - the userid of the account being connected to
74      *   * GET_IMAP_ID_HOST - the hostname of the server being connected to
75      *   * GET_IMAP_ID_CAPA - the values returned by the "CAPA" command
76      *
77      * For default behavior (no values inserted), return the empty bundle.
78      * To insert additional values into the IMAP ID command, return a bundle containing a single
79      * entry with a key of GET_IMAP_ID and a String value.  The value must be field/value pairs
80      * surrounded by quotes and separated by spaces.  Multiple field/value pairs may be provided.
81      * See RFC 2971 for more information.
82      */
83     private static final String GET_IMAP_ID = "getImapId";
84     private static final String GET_IMAP_ID_USER = "getImapId.user";
85     private static final String GET_IMAP_ID_HOST = "getImapId.host";
86     private static final String GET_IMAP_ID_CAPA = "getImapId.capabilities";
87 
88     /**
89      * This policy request allows you to supply preset server configurations to provide
90      * automatic setup/configuration for specific email providers.  These values supplement (or
91      * override) the automatic configurations provided in res/xml/providers.xml in
92      * the Email sources.  (See that file for more information and plenty of samples.)
93      *
94      * The only argument (with the key FIND_PROVIDER) is a string containing the domain that the
95      * user entered as part of their email address;  For example, if the user enters
96      * "MyEmailAddress@gmail.com", the domain will be "gmail.com".
97      *
98      * If no server information is provided for this domain, simply return Bundle.EMPTY.
99      * If server information is available for this domain, it can be returned in the following
100      * values:
101      *   * FIND_PROVIDER_IN_URI The server configuration for the incoming (IMAP or POP) server
102      *   * FIND_PROVIDER_IN_USER Format of the username (login) value
103      *   * FIND_PROVIDER_OUT_URI The server configuration for the outgoing (SMTP) server
104      *   * FIND_PROVIDER_OUT_USER Format of the username (login) value
105      *
106      * Valid incoming uri schemes are:
107      *     imap        IMAP with no transport security.
108      *     imap+tls+   IMAP with required TLS transport security.
109      *                     If TLS is not available the connection fails.
110      *     imap+ssl+   IMAP with required SSL transport security.
111      *                     If SSL is not available the connection fails.
112      *
113      *     pop3        POP3 with no transport security.
114      *     pop3+tls+   POP3 with required TLS transport security.
115      *                     If TLS is not available the connection fails.
116      *     pop3+ssl+   POP3 with required SSL transport security.
117      *                     If SSL is not available the connection fails.
118      *
119      * Valid outgoing uri schemes are:
120      *     smtp        SMTP with no transport security.
121      *     smtp+tls+   SMTP with required TLS transport security.
122      *                     If TLS is not available the connection fails.
123      *     smtp+ssl+   SMTP with required SSL transport security.
124      *                     If SSL is not available the connection fails.
125      *
126      * To the above schemes you may also add "trustallcerts" to indicate that,
127      * although link encryption is still required, "non-trusted" certificates may
128      * will be excepted.  For example, "imap+ssl+trustallcerts" or
129      * "smtp+tls+trustallcerts".  This should only used when necessary, as it
130      * could allow a spoofed server to intercept password and mail.
131      *
132      * The URIs should be full templates for connection, including a port if
133      * the service uses a non-default port.  The default ports are as follows:
134      *     imap        143     pop3        110     smtp        587
135      *     imap+tls+   143     pop3+tls+   110     smtp+tls+   587
136      *     imap+ssl+   993     pop3+ssl+   995     smtp+ssl+   465
137      *
138      * The username attribute is used to supply a template for the username
139      * that will be presented to the server. This username is built from a
140      * set of variables that are substituted with parts of the user
141      * specified email address.
142      *
143      * Valid substitution values for the username attribute are:
144      *     $email - the email address the user entered
145      *     $user - the value before the @ sign in the email address the user entered
146      *     $domain - the value after the @ signin the email address the user entered
147      *
148      * The username attribute MUST be specified for the incoming element, so the POP3 or IMAP
149      * server can identify the mailbox to be opened.
150      *
151      * The username attribute MAY be the empty string for the outgoing element, but only if the
152      * SMTP server supports anonymous transmission (most don't).
153      *
154      * For more information about these values, and many examples, see res/xml/providers.xml in
155      * the Email sources.
156      */
157     private static final String FIND_PROVIDER = "findProvider";
158     private static final String FIND_PROVIDER_IN_URI = "findProvider.inUri";
159     private static final String FIND_PROVIDER_IN_USER = "findProvider.inUser";
160     private static final String FIND_PROVIDER_OUT_URI = "findProvider.outUri";
161     private static final String FIND_PROVIDER_OUT_USER = "findProvider.outUser";
162 
163     /**
164      * The following data is simply examples, and would be changed (or removed) based on the
165      * requirements for your device.
166      */
167 
168     /**
169      * Sample: Email domains that will be auto-configured.  In our example, a number of domains
170      * are controlled by a single mail server.
171      */
172     private static final String[] KNOWN_DOMAINS = new String[] {
173         "physics.school.edu", "math.school.edu", "language.school.edu", "history.school.edu"
174     };
175 
176     /**
177      * Sample: When we see a particular capability (identifying a particular server), send
178      * back a special value in the IMAP ID command.
179      */
180     private static final String MY_SERVER_CAPABILITY = "MY-SERVER-CAPABILITY";
181     private static final String MY_DEVICE_ID = "\"DEVICE-ID-FIELD\" \"MY-DEVICE-ID-VALUE\"";
182 
183     /**
184      * Entry point from the Email application.
185      *
186      * @param policy A string requesting a particular policy
187      * @param arguments A bundle containing zero or more argument values for the requested policy
188      * @return A bundle containing zero or more return values for the requested policy
189      */
getPolicy(String policy, Bundle arguments)190     public static Bundle getPolicy(String policy, Bundle arguments) {
191         /*
192          * Policy: Use alternate exchange strings
193          */
194         if (USE_ALTERNATE_EXCHANGE_STRINGS.equals(policy)) {
195             // Un-comment the following code to select alternate exchange strings
196             // Bundle alternates = new Bundle();
197             // alternates.putBoolean(USE_ALTERNATE_EXCHANGE_STRINGS, true);
198             // return alternates;
199         }
200 
201         /*
202          * Policy: For a known domain, configure to the servers for that domain
203          */
204         if (FIND_PROVIDER.equals(policy)) {
205             String domain = arguments.getString(FIND_PROVIDER);
206             if (domain != null) {
207                 domain = domain.toLowerCase();
208                 boolean isKnownDomain = false;
209                 for (String knownDomain : KNOWN_DOMAINS) {
210                     if (knownDomain.equals(domain)) {
211                         isKnownDomain = true;
212                         break;
213                     }
214                 }
215                 if (isKnownDomain) {
216                     Bundle b = new Bundle();
217                     b.putString(FIND_PROVIDER_IN_URI, "imap+ssl://imap.school.edu");
218                     b.putString(FIND_PROVIDER_IN_USER, "$email");
219                     b.putString(FIND_PROVIDER_OUT_URI, "smtp+ssl://smtp.school.edu");
220                     b.putString(FIND_PROVIDER_OUT_USER, "$email");
221                     return b;
222                 }
223             }
224         }
225 
226         /**
227          * Policy:  If the IMAP server presents a particular capability, send back a particular
228          * identifier in the IMAP ID.
229          */
230         if (GET_IMAP_ID.equals(policy)) {
231             String capabilities = arguments.getString(GET_IMAP_ID_CAPA);
232             if (capabilities != null) {
233                 if (capabilities.toUpperCase().contains(MY_SERVER_CAPABILITY)) {
234                     Bundle b = new Bundle();
235                     b.putString(GET_IMAP_ID, MY_DEVICE_ID);
236                     return b;
237                 }
238             }
239         }
240 
241         /**
242          * For any other policy request, or any policy request that cannot be processed,
243          * return an empty bundle.
244          */
245         return Bundle.EMPTY;
246     }
247 }
248