├── .gitignore ├── .tx └── config ├── AndroidManifest.xml ├── ChangeLog ├── LICENSE ├── README.md ├── artwork ├── blitzmail.svg ├── gplay_feature.png ├── gplay_promo.png ├── ic_launcher_note.svg ├── ic_stat_notify.svg ├── screen_MainActivity.png ├── screen_MainActivity_de.png ├── screen_NoteActivity.png ├── screen_SendMailActivity.png ├── screen_SendMailActivity_de.png ├── screen_ShareVia.png ├── screen_ShareVia_de.png └── twitter.png ├── build.gradle ├── flavors └── pro │ └── res │ └── values │ └── strings.xml ├── gradle.properties ├── ic_launcher-web.png ├── ic_launcher_note-web.png ├── res ├── drawable-hdpi-v11 │ ├── ic_stat_notify.png │ └── ic_stat_notify_2.png ├── drawable-hdpi │ ├── ic_action_cancel.png │ ├── ic_action_send_later.png │ ├── ic_action_try_again.png │ ├── ic_launcher.png │ ├── ic_launcher_note.png │ ├── ic_stat_notify.png │ └── ic_stat_notify_2.png ├── drawable-mdpi-v11 │ ├── ic_stat_notify.png │ └── ic_stat_notify_2.png ├── drawable-mdpi │ ├── ic_action_cancel.png │ ├── ic_action_send_later.png │ ├── ic_action_try_again.png │ ├── ic_launcher.png │ ├── ic_launcher_note.png │ ├── ic_stat_notify.png │ └── ic_stat_notify_2.png ├── drawable-xhdpi-v11 │ ├── ic_stat_notify.png │ └── ic_stat_notify_2.png ├── drawable-xhdpi │ ├── ic_action_cancel.png │ ├── ic_action_send_later.png │ ├── ic_action_try_again.png │ ├── ic_launcher.png │ ├── ic_launcher_note.png │ ├── ic_stat_notify.png │ └── ic_stat_notify_2.png ├── drawable-xxhdpi-v11 │ ├── ic_stat_notify.png │ └── ic_stat_notify_2.png ├── drawable-xxhdpi │ ├── ic_action_cancel.png │ ├── ic_action_send_later.png │ ├── ic_action_try_again.png │ ├── ic_launcher.png │ ├── ic_launcher_note.png │ ├── ic_stat_notify.png │ └── ic_stat_notify_2.png ├── drawable-xxxhdpi │ ├── ic_action_cancel.png │ ├── ic_action_send_later.png │ ├── ic_action_try_again.png │ ├── ic_launcher.png │ └── ic_launcher_note.png ├── drawable │ ├── ic_delete.xml │ └── notification_icon.xml ├── layout │ ├── activity_main.xml │ └── activity_note.xml ├── values-de │ └── strings.xml ├── values-es │ └── strings.xml ├── values-fa │ └── strings.xml ├── values-fr │ └── strings.xml ├── values-it │ └── strings.xml ├── values-ja │ └── strings.xml ├── values-kab │ └── strings.xml ├── values-nb │ └── strings.xml ├── values-nl │ └── strings.xml ├── values-pl │ └── strings.xml ├── values-pt-rBR │ └── strings.xml ├── values-pt-rPT │ └── strings.xml ├── values-tr │ └── strings.xml ├── values │ ├── arrays.xml │ ├── colors.xml │ ├── strings.xml │ └── styles.xml └── xml │ └── preferences.xml └── src ├── com └── provider │ └── JSSEProvider.java └── de └── grobox └── blitzmail ├── MailStorage.java ├── MainActivity.kt ├── NoteActivity.java ├── PrivateConstants.sample_java ├── crypto ├── Crypto.java └── EncryptedEditTextPreference.java ├── notification ├── MailNotificationManager.kt └── NotificationHandlerActivity.kt ├── preferences ├── MailPreferences.kt └── PrefFragment.java └── send ├── MailSender.java ├── SendActivity.java ├── SendLaterWorker.kt └── SenderService.kt /.gitignore: -------------------------------------------------------------------------------- 1 | # private files 2 | PrivateConstants.java 3 | 4 | # built application files 5 | *.apk 6 | *.ap_ 7 | 8 | # files for the dex VM 9 | *.dex 10 | 11 | # Java class files 12 | *.class 13 | 14 | # generated files 15 | bin/ 16 | gen/ 17 | build/ 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | # Android Studio files 23 | .idea/ 24 | *.iml 25 | .gradle/ 26 | -------------------------------------------------------------------------------- /.tx/config: -------------------------------------------------------------------------------- 1 | [main] 2 | host = https://www.transifex.com 3 | lang_map = pt_BR: pt-rBR, pt_PT: pt-rPT 4 | 5 | [blitzmail.strings] 6 | file_filter = res/values-/strings.xml 7 | source_lang = en 8 | source_file = res/values/strings.xml 9 | type = ANDROID 10 | minimum_perc = 10 11 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 19 | 20 | 26 | 27 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 69 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | Version 0.6 2 | * Material Design 3 | * New logo 4 | * Allow files and images to be blitzmailed 5 | * Send mails automatically when connectivity is restored 6 | * some bugfixes 7 | 8 | Version 0.5 9 | * added BlitzNote to quickly send a short note 10 | * Holo theme for dialogs on devices that support it (3+) 11 | * do not set Sender mail header (wrong headers for some servers) 12 | * switched to gradle buildsystem 13 | 14 | Version 0.4 15 | * new option to queue mail when offline 16 | * new option in preferences to send all queued mail 17 | * new notification icon when sending mail 18 | * allow to be moved/installed to SD card 19 | 20 | Version 0.3 21 | * new property: Sender Name 22 | * set mail header From: 23 | * set mail header Date: 24 | * improved error message for untrusted mail server certificates 25 | 26 | Version 0.2 27 | * German Translation 28 | * using status bar for notifications 29 | * notification about successful sending can be turned off 30 | * check for internet connectivity before mailing 31 | 32 | Version 0.1 33 | * First Version 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published by 637 | the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | BlitzMail 2 | ========= 3 | Share content via email with just one click! 4 | 5 | ![BlitzMail Logo](/res/drawable-xhdpi/ic_launcher.png) 6 | 7 | BlitzMail is an Android app that allows you to set up your email account once 8 | and then use it to send emails or quick notes to an address of your choice. 9 | This comes in handy when you need to send a lot of things via email, 10 | because you are in a low connectivity area (e.g. subway) 11 | and want to remember things to look at later. 12 | 13 | It also works when you are offline. 14 | BlitzMail then queues your emails 15 | and allows you to send them later when you have connectivity again. 16 | 17 | The SMTP password is stored encrypted with a built-in key and salted with your device ID. 18 | This is not fully secure, but should provide reasonable protection for your password. 19 | 20 | [![Flattr me](https://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/thing/1217295) 21 | [![Follow @BlitzMailApp](artwork/twitter.png)](https://twitter.com/BlitzMailApp) 22 | 23 | Get BlitzMail 24 | ------------- 25 | 26 | [Get it on F-Droid](https://f-droid.org/packages/de.grobox.blitzmail/) 29 | [Get it on Google Play](https://play.google.com/store/apps/details?id=de.grobox.blitzmail.pro) 32 | 33 | Screenshots 34 | ----------- 35 | 36 | [](/artwork/screen_ShareVia.png) 37 | [](/artwork/screen_SendMailActivity.png) 38 | [](/artwork/screen_NoteActivity.png) 39 | [](/artwork/screen_MainActivity.png) 40 | 41 | Contributing 42 | ------------ 43 | 44 | Contributions are both encouraged and appreciated. If you want to do more than fixing bugs, please talk to me *before* doing any major work so that we can coordinate, prevent duplicated work and discuss the best approach for your undertaking. 45 | 46 | Missing features are documented in the [issue tracker](https://github.com/grote/BlitzMail/issues?labels=enhancement&state=open). Feel free to look there for ideas or to add your own. 47 | 48 | ### Translate BlitzMail Into Your Language ### 49 | 50 | Translating BlitzMail is very easy. Just sign up for an account at [Transifex](https://www.transifex.com). After you are logged in, go to the [BlitzMail translation project](https://www.transifex.com/projects/p/blitzmail/). There you can click the "Request language" button if your language does not exist, or if you want to improve existing translations, apply for the respective language team. 51 | 52 | What you translate there will then be included in the next release of BlitzMail. 53 | 54 | Please do not send translations as a pull request in GitHub since this not only causes more work, but also might overwrite other people's translations in Transifex. 55 | 56 | ### Building from Source ### 57 | 58 | Before building BlitzMail from source, make sure to run the following command. 59 | 60 | ```bash 61 | cp src/de/grobox/blitzmail/PrivateConstants.sample_java src/de/grobox/blitzmail/PrivateConstants.java 62 | ``` 63 | 64 | Then edit `src/de/grobox/blitzmail/PrivateConstants.java` and replace `[Please insert your encryption key here]` with the encryption key of your choice. 65 | 66 | License 67 | ------- 68 | 69 | ![GNU AGPLv3 Image](https://www.gnu.org/graphics/agplv3-88x31.png) 70 | 71 | This program is Free Software: You can use, study share and improve it at your 72 | will. Specifically you can redistribute and/or modify it under the terms of the 73 | [GNU Affero General Public License](https://www.gnu.org/licenses/agpl.html) as 74 | published by the Free Software Foundation, either version 3 of the License, or 75 | (at your option) any later version. 76 | -------------------------------------------------------------------------------- /artwork/blitzmail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 24 | 26 | 30 | 34 | 35 | 45 | 55 | 65 | 75 | 86 | 89 | 93 | 97 | 98 | 100 | 104 | 108 | 109 | 111 | 115 | 119 | 120 | 122 | 126 | 130 | 131 | 133 | 137 | 141 | 142 | 144 | 148 | 152 | 153 | 155 | 159 | 163 | 164 | 166 | 170 | 174 | 175 | 177 | 181 | 185 | 186 | 188 | 192 | 196 | 197 | 199 | 203 | 207 | 211 | 212 | 219 | 228 | 230 | 234 | 238 | 239 | 250 | 257 | 261 | 265 | 266 | 277 | 280 | 284 | 288 | 289 | 298 | 301 | 305 | 309 | 310 | 321 | 323 | 327 | 331 | 332 | 343 | 354 | 357 | 361 | 365 | 366 | 377 | 384 | 388 | 392 | 393 | 404 | 406 | 410 | 414 | 415 | 426 | 433 | 437 | 441 | 442 | 453 | 460 | 464 | 468 | 469 | 479 | 486 | 490 | 494 | 495 | 505 | 507 | 511 | 515 | 519 | 520 | 530 | 540 | 543 | 547 | 551 | 552 | 563 | 571 | 575 | 579 | 580 | 591 | 601 | 611 | 614 | 618 | 619 | 620 | 642 | 644 | 645 | 647 | image/svg+xml 648 | 650 | 651 | 652 | 653 | 654 | 659 | 664 | 670 | 671 | 676 | 682 | 688 | 694 | 700 | 706 | 707 | 711 | 718 | 719 | 723 | 730 | 731 | 732 | 733 | -------------------------------------------------------------------------------- /artwork/gplay_feature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/artwork/gplay_feature.png -------------------------------------------------------------------------------- /artwork/gplay_promo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/artwork/gplay_promo.png -------------------------------------------------------------------------------- /artwork/ic_stat_notify.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /artwork/screen_MainActivity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/artwork/screen_MainActivity.png -------------------------------------------------------------------------------- /artwork/screen_MainActivity_de.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/artwork/screen_MainActivity_de.png -------------------------------------------------------------------------------- /artwork/screen_NoteActivity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/artwork/screen_NoteActivity.png -------------------------------------------------------------------------------- /artwork/screen_SendMailActivity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/artwork/screen_SendMailActivity.png -------------------------------------------------------------------------------- /artwork/screen_SendMailActivity_de.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/artwork/screen_SendMailActivity_de.png -------------------------------------------------------------------------------- /artwork/screen_ShareVia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/artwork/screen_ShareVia.png -------------------------------------------------------------------------------- /artwork/screen_ShareVia_de.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/artwork/screen_ShareVia_de.png -------------------------------------------------------------------------------- /artwork/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/artwork/twitter.png -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.31' 3 | repositories { 4 | jcenter() 5 | google() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.4.1' 9 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 10 | } 11 | } 12 | 13 | allprojects { 14 | repositories { 15 | google() 16 | jcenter() 17 | } 18 | } 19 | 20 | apply plugin: 'com.android.application' 21 | apply plugin: 'kotlin-android' 22 | 23 | dependencies { 24 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" 25 | 26 | implementation 'androidx.appcompat:appcompat:1.0.2' 27 | implementation "android.arch.work:work-runtime-ktx:1.0.1" 28 | 29 | implementation 'com.sun.mail:android-mail:1.6.3' 30 | } 31 | 32 | android { 33 | defaultConfig { 34 | versionCode 14 35 | versionName "0.7.1" 36 | 37 | compileSdkVersion 28 38 | targetSdkVersion 28 39 | minSdkVersion 14 40 | buildToolsVersion "28.0.3" 41 | } 42 | 43 | flavorDimensions "version" 44 | productFlavors { 45 | normal { 46 | applicationId "de.grobox.blitzmail" 47 | buildConfigField "boolean", "PRO", "true" 48 | dimension "version" 49 | } 50 | 51 | pro { 52 | applicationId "de.grobox.blitzmail.pro" 53 | buildConfigField "boolean", "PRO", "true" 54 | dimension "version" 55 | } 56 | 57 | lite { 58 | applicationId "de.grobox.blitzmail.lite" 59 | buildConfigField "boolean", "PRO", "false" 60 | dimension "version" 61 | } 62 | } 63 | 64 | sourceSets { 65 | main { 66 | manifest.srcFile 'AndroidManifest.xml' 67 | java.srcDirs = ['src'] 68 | resources.srcDirs = ['src'] 69 | aidl.srcDirs = ['src'] 70 | renderscript.srcDirs = ['src'] 71 | res.srcDirs = ['res'] 72 | assets.srcDirs = ['assets'] 73 | } 74 | } 75 | 76 | android.sourceSets.pro { 77 | res.srcDir 'flavors/pro/res' 78 | } 79 | 80 | /* 81 | * To sign release build, create file gradle.properties in ~/.gradle/ with this content: 82 | * 83 | * signingStoreLocation=/home/key.store 84 | * signingStorePassword=xxx 85 | * signingKeyAlias=alias 86 | * signingKeyPassword=xxx 87 | */ 88 | if (project.hasProperty('signingStoreLocation') && 89 | project.hasProperty('signingStorePassword') && 90 | project.hasProperty('signingKeyAlias') && 91 | project.hasProperty('signingKeyPassword')) { 92 | println "Found sign properties in gradle.properties! Signing build…" 93 | 94 | signingConfigs { 95 | release { 96 | storeFile file(signingStoreLocation) 97 | storePassword signingStorePassword 98 | keyAlias signingKeyAlias 99 | keyPassword signingKeyPassword 100 | } 101 | } 102 | 103 | buildTypes.release.signingConfig = signingConfigs.release 104 | } else { 105 | buildTypes.release.signingConfig = null 106 | } 107 | 108 | // Do not abort build if lint finds errors 109 | lintOptions { 110 | abortOnError false 111 | disable 'MissingTranslation' 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /flavors/pro/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BlitzMail Pro 5 | BlitzNote Pro 6 | 7 | 8 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | android.enableJetifier=true 2 | android.useAndroidX=true -------------------------------------------------------------------------------- /ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/ic_launcher-web.png -------------------------------------------------------------------------------- /ic_launcher_note-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/ic_launcher_note-web.png -------------------------------------------------------------------------------- /res/drawable-hdpi-v11/ic_stat_notify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-hdpi-v11/ic_stat_notify.png -------------------------------------------------------------------------------- /res/drawable-hdpi-v11/ic_stat_notify_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-hdpi-v11/ic_stat_notify_2.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_action_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-hdpi/ic_action_cancel.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_action_send_later.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-hdpi/ic_action_send_later.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_action_try_again.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-hdpi/ic_action_try_again.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher_note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-hdpi/ic_launcher_note.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_stat_notify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-hdpi/ic_stat_notify.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_stat_notify_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-hdpi/ic_stat_notify_2.png -------------------------------------------------------------------------------- /res/drawable-mdpi-v11/ic_stat_notify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-mdpi-v11/ic_stat_notify.png -------------------------------------------------------------------------------- /res/drawable-mdpi-v11/ic_stat_notify_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-mdpi-v11/ic_stat_notify_2.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_action_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-mdpi/ic_action_cancel.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_action_send_later.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-mdpi/ic_action_send_later.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_action_try_again.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-mdpi/ic_action_try_again.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher_note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-mdpi/ic_launcher_note.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_stat_notify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-mdpi/ic_stat_notify.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_stat_notify_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-mdpi/ic_stat_notify_2.png -------------------------------------------------------------------------------- /res/drawable-xhdpi-v11/ic_stat_notify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xhdpi-v11/ic_stat_notify.png -------------------------------------------------------------------------------- /res/drawable-xhdpi-v11/ic_stat_notify_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xhdpi-v11/ic_stat_notify_2.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_action_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xhdpi/ic_action_cancel.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_action_send_later.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xhdpi/ic_action_send_later.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_action_try_again.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xhdpi/ic_action_try_again.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher_note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xhdpi/ic_launcher_note.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_stat_notify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xhdpi/ic_stat_notify.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_stat_notify_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xhdpi/ic_stat_notify_2.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi-v11/ic_stat_notify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxhdpi-v11/ic_stat_notify.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi-v11/ic_stat_notify_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxhdpi-v11/ic_stat_notify_2.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_action_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxhdpi/ic_action_cancel.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_action_send_later.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxhdpi/ic_action_send_later.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_action_try_again.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxhdpi/ic_action_try_again.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_launcher_note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxhdpi/ic_launcher_note.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_stat_notify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxhdpi/ic_stat_notify.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_stat_notify_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxhdpi/ic_stat_notify_2.png -------------------------------------------------------------------------------- /res/drawable-xxxhdpi/ic_action_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxxhdpi/ic_action_cancel.png -------------------------------------------------------------------------------- /res/drawable-xxxhdpi/ic_action_send_later.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxxhdpi/ic_action_send_later.png -------------------------------------------------------------------------------- /res/drawable-xxxhdpi/ic_action_try_again.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxxhdpi/ic_action_try_again.png -------------------------------------------------------------------------------- /res/drawable-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xxxhdpi/ic_launcher_note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grote/BlitzMail/20dd8972f82404e2bd4f09d2999cd712e735887e/res/drawable-xxxhdpi/ic_launcher_note.png -------------------------------------------------------------------------------- /res/drawable/ic_delete.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /res/drawable/notification_icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 12 | -------------------------------------------------------------------------------- /res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /res/layout/activity_note.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /res/values-de/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Senden 4 | E-Mail gesendet 5 | Verschicke E-Mail 6 | Sende, bitte warten… 7 | Erneut versuchen 8 | Später senden 9 | Wegwerfen 10 | Senden 11 | E-Mail-Server Einstellungen 12 | Server erfordert keine Authentifizierung 13 | Server erfordert Authentifizierung 14 | SMTP Server 15 | SMTP Port 16 | SMTP Authentifizierung 17 | Benutzername 18 | Passwort 19 | E-Mails werden an diese Adresse gesendet 20 | Empfänger-Adresse 21 | Absenderadresse 22 | Absendername 23 | E-Mails erscheinen, als ob sie von dieser Adresse kommen 24 | Verschlüsselung 25 | Wartende E-Mails jetzt verschicken 26 | Es warten %d E-Mails darauf verschickt zu werden 27 | Fehler 28 | Bitte konfigurieren Sie diese Einstellung: 29 | Habe keinen Inhalt für die E-Mail erhalten. Sie wird nicht gesendet, denn sie wäre leer. 30 | Authentifizierung fehlgeschlagen. Bitte überprüfen Sie den Benutzernamen und das Passwort! 31 | Der Server antwortete mit folgendem Fehler. Bitte überprüfen Sie die SMTP-Einstellungen. 32 | Es besteht keine Verbindung zum Internet. Bitte stellen Sie die Verbindung her und versuchen Sie es erneut. 33 | Ihr Android-System vertraut dem SSL Zertifikat Ihres Servers nicht. Bitte importieren Sie das Zertifikat ins System und versuchen es dann erneut. 34 | Das Passwort konnte nicht entschlüsselt werden. Haben Sie die App auf ein anderes Gerät kopiert? Bitte geben Sie das E-Mail-Passwort in den Einstellungen neu ein. 35 | Leider steht diese Funktion nur in BlitzMail Pro zur Verfügung. Bitte kaufen Sie diese Version, um alle Funktionen nutzen zu können und die Entwicklung dieser App zu unterstützen. 36 | Zeitüberschreitung bei der Verbindung zum Server. Bitte versuchen Sie es später erneut oder prüfen Sie die SMTP-Einstellungen. 37 | Die Methode zum Aufruf von BlitzMail wird nicht unterstützt. Bitte senden Sie dem Entwickler was Sie getan haben, um diesen Fehler auszulösen! 38 | Der Anhang der E-Mail konnte nicht geladen werden. 39 | Datei nicht gefunden! Wurde sie vielleicht vor dem Senden der E-Mail gelöscht? 40 | E-Mail konnte ohne die erforderliche Berechtigung nicht gesendet werden. 41 | Keine Zugriffsberechtigung. Bitte erteilen Sie die Berechtigung in den Einstellungen! 42 | Verhalten 43 | Benachrichtigung über versendete E-Mail 44 | Zeige eine Benachrichtigung nachdem eine E-Mail erfolgreich verschickt wurde. 45 | Zeige keine Benachrichtigung nachdem eine E-Mail erfolgreich verschickt wurde. 46 | Datei(en) teilen mit 47 | Speichern 48 | Nichts zu versenden 49 | 50 | -------------------------------------------------------------------------------- /res/values-es/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Enviar 4 | Mensajes enviados 5 | Enviando BlitzMail 6 | Envío en curso; espere… 7 | Intentar otra vez 8 | Enviar más tarde 9 | Descartar 10 | Enviando 11 | Configuración del servidor de correo 12 | El servidor no necesita identificación. 13 | El servidor necesita identificación. 14 | Servidor SMTP 15 | Puerto SMTP 16 | Autenticación de SMTP 17 | Nombre de usuario 18 | Contraseña 19 | Los mensajes se enviarán a esta dirección 20 | Dirección de destinatario 21 | Dirección de remitente 22 | Nombre de remitente 23 | Los mensajes aparentarán provenir de esta dirección 24 | Cifrado 25 | Enviar mensajes en cola ahora 26 | Hay %d mensajes en espera para su envío 27 | Error 28 | Configure esta opción: 29 | No se obtuvo el cuerpo ni el asunto. No se envió el mensaje porque estaría vacío. 30 | Falló la autenticación. Revise su nombre de usuario y contraseña. 31 | El servidor devolvió el siguiente error. Revise su configuración de SMTP. 32 | No hay conexión a Internet. Establezca la conectividad e intente de nuevo. 33 | Su sistema Android no confía en el certificado SSL de su servidor. Importe el certificado e inténtelo de nuevo. 34 | No se pudo descifrar su contraseña. ¿Ha trasladado la aplicación a otro dispositivo? Escriba la contraseña otra vez en la configuración. 35 | Lamentablemente, esta funcionalidad solo está disponible en BlitzMail Pro. Obtenga esta versión para acceder a todas las funciones y apoyar el desarrollo de esta aplicación. 36 | Se agotó el tiempo de espera de la conexión con el servidor de correo. Inténtelo más tarde o revise su configuración de SMTP. 37 | Forma no admitida de llamar a BlitzMail. ¡Por favor, informa a los desarrolladores de lo que hiciste para causar esto! 38 | No se pudo obtener el archivo adjunto para el correo. 39 | No se encontró el archivo. Posiblemente se eliminó antes de intentar enviar el mensaje. 40 | No puedo enviar correo electrónico sin los permisos necesarios. 41 | No tengo permisos para acceder a los archivos. Conceda estos permisos en los ajustes. 42 | Interfaz 43 | Mostrar notificaciones de correo enviado 44 | Mostrar notificación en la barra de estado después de que el correo haya sido enviado 45 | No mostrar notificación en la barra de estado después de que el correo haya sido enviado 46 | Archivo(s) compartido con 47 | Guardar 48 | No hay nada que enviar 49 | 50 | -------------------------------------------------------------------------------- /res/values-fa/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ارسال 4 | ایمیل ارسال شد 5 | در حال ارسال BlitzMail 6 | در حال ارسال لطفا صبر کنید... 7 | دوباره تلاش کنید 8 | بعداً بفرست 9 | رد کردن 10 | در حال ارسال 11 | تنظیمات سرور ایمیل 12 | سرور نیاز به احراز هویت ندارد 13 | سرور نیاز به احراز هویت دارد 14 | سرور SMTP 15 | پورت SMTP 16 | احراز هویت SMTP 17 | نام کاربری 18 | رمز عبور 19 | ایمیل ها به این آدرس فرستاده خواهند شد 20 | آدرس گیرنده 21 | آدرس فرستنده 22 | نام فرستنده 23 | ایمیل ها به نظر از این آدرس دریافت خواهند شد 24 | رمزنگاری 25 | ارسال ایمیل های در صف همین الان 26 | %d ایمیل آماده برای ارسال وجود دارد 27 | خطاء 28 | لطفا این گزینه را تنظیم کنید: 29 | هیچ عنوان یا متنی وجود ندارد. ایمیل نمی تواند فرستاده شود چون خالی خواهد بود. 30 | احراز هویت ناموفق بود. لطفا نام کاربری و رمز عبور خود را چک کنید! 31 | سرور خطای ذیل را برگرداند. لطفاً تنظیمات SMTP را چک کنید. 32 | هیچ اتصالی به اینترنت یافت نشد. لطفا اتصال را برقرار کرده و دوباره تلاش کنید. 33 | گواهینامه SSL سرور توسط سیستم اندروید شما معتبر شناخته نشد. لطفا گواهینامه را ایمپورت کرده و دوباره تلاش کنید. 34 | رمز عبور شما رمزگشایی نشد. آیا برنامه را به دستگاه دیگری انتقال دادید؟ لطفا رمز عبور خود را دوباره در تنظیمات وارد کنید. 35 | متاسفانه، این ویژگی فقط در پرو BlitzMail موجود می باشد. لطفاً این نسخه را برای دسترسی به تمام امکانات و حمایت از توسعه این برنامه دریافت کنید. 36 | اتصال به سرور ایمیل قطع شد. لطفاً بعداً دوباره تلاش کنید یا تنظیمات SMTP را چک کنید. 37 | روش فراخوانی BlitzMail پشتیبانی نمی شود. لطفاً به توسعه دهنده گزارش دهید که چه چیزی باعث این اتفاق شد! 38 | ضمیمه ایمیل گرفته نشد. 39 | فایل یافت نشد! شاید از زمانی که شما میخواستید ایمیل را ارسال کنید پاک شده است؟ 40 | ایمیل بدون دسترسی لازم نمی تواند ارسال شود. 41 | اجازه لازم برای دسترسی به فایل وجود ندارد. لطفا اجازه دسترسی را در تنظیمات بدهید! 42 | رابط 43 | نمایش نوتیفیکیشن برای ایمیل ارسال شده 44 | نمایش نوتیفیکیشن در نوار حالت بعد از اینکه ایمیل ارسال شد 45 | بعد از اینکه ایمیل ارسال شد نوتیفیکیشن را در نوار حالت نمایش نده 46 | فایل (ها) اشتراک گذاشته شده با 47 | ذخیره 48 | چیزی برای ارسال وجود ندارد 49 | 50 | -------------------------------------------------------------------------------- /res/values-fr/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Envoyer 4 | Courriel envoyé 5 | Envoi du courriel BlitzMail 6 | Envoi, veuillez patienter… 7 | Ressayer 8 | Envoyer plus tard 9 | Annuler 10 | Envoi 11 | Paramètres du serveur de courriel 12 | Le serveur n’exige pas d’authentification 13 | Le serveur exige une authentification 14 | Serveur SMTP 15 | Port SMTP 16 | Auth. SMTP 17 | Nom d’utilisateur 18 | Mot de passe 19 | Les courriels seront envoyés à cette adresse 20 | Adresse du destinataire 21 | Adresse de l’expéditeur 22 | Nom de l’expéditeur 23 | Les courriels s’afficheront comme envoyés par cette adresse 24 | Chiffrement 25 | Envoyer maintenant les courriels en attente 26 | Il y a %d courriels en attente d’envoi 27 | Erreur 28 | Veuillez définir cette option : 29 | Aucun corps ou objet. Le courriel n’a pas été envoyé, car il serait vide. 30 | Échec d’authentification. Veuillez vérifier vos nom d’utilisateur et mot de passe ! 31 | Le serveur a retourné l’erreur suivante. Veuillez vérifier vos paramètres SMTP. 32 | Aucune connexion trouvée vers Internet. Veuillez en établir une et ressayer. 33 | Le certificat SSL de votre serveur n’est pas considéré comme fiable par votre système Android. Veuillez importer le certificat puis ressayer. 34 | Impossible de déchiffrer votre mot de passe. Avez-vous déplacé l’appli vers un autre appareil ? Veuillez saisir votre mot de passe de nouveau dans les paramètres. 35 | Malheureusement, cette fonction est seulement proposée sur BlitzMail Pro. Veuillez l’acquérir pour utiliser toutes les fonctions et soutenir le développement de cette appli. 36 | Temporisation de connexion au serveur de courriel. Veuillez ressayer ultérieurement ou vérifier vos paramètres SMTP. 37 | Cette façon d’appeler BlitzMail n’est pas prise en charge ! Veuillez signaler ce que vous pourriez avoir fait pour causer cela en contactant le développeur. 38 | Impossible de récupérer la pièce jointe du courriel. 39 | Le fichier est introuvable ! Peut-être a-t-il été supprimé depuis la tentative d’envoi du courriel ? 40 | Impossible d’envoyer le courriel sans droit d’accès. 41 | Impossible d’accéder au fichier. Veuillez accorder le droit dans les paramètres ! 42 | Interface 43 | Afficher une notification de courriel envoyé 44 | Afficher une notification dans la barre d’état après l’envoi d’un courriel 45 | Ne pas afficher une notification dans la barre d’état après l’envoi d’un courriel 46 | Fichier(s) partagé(s) avec 47 | Enregistrer 48 | Rien à envoyer 49 | 50 | -------------------------------------------------------------------------------- /res/values-it/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Invia 4 | Invia email 5 | Invio BlitzMail 6 | Invio attendere prego... 7 | Prova di nuovo 8 | Invia dopo 9 | Annulla 10 | Invio 11 | Impostazioni server email 12 | Il server non richiede l\'autenticazione 13 | Il server richiedere l\'autenticazione 14 | Server SMTP 15 | Porta SMTP 16 | Autenticazione SMTP 17 | Nome utente 18 | Password 19 | Le email verranno inviate a questo indirizzo 20 | Indirizzo mittente 21 | Nome mittente 22 | Le email sembreranno inviate da questo indirizzo 23 | Invia email in coda adesso 24 | Errore 25 | Imposta questa opzione: 26 | Interfaccia 27 | Mostra notifiche per le email inviate 28 | Mostra notifiche nella barra di stato dopo che le email sono state inviate 29 | Non mostrare le notifiche nella barra di stato dopo che le mail sono state inviate 30 | Salva 31 | Niente da inviare 32 | 33 | -------------------------------------------------------------------------------- /res/values-ja/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 送信 4 | メールを送信 5 | BlitzMail の送信中 6 | 送信中、しばらくお待ちください… 7 | 再試行 8 | 後で送信 9 | 消去 10 | 送信中 11 | メールサーバー設定 12 | サーバーは認証が必要ありません 13 | サーバーは認証が必要です 14 | SMTP サーバー 15 | SMTP ポート 16 | SMTP 認証 17 | ユーザー名 18 | パスワード 19 | メールはこのアドレスに送信されます 20 | 受信者のアドレス 21 | 送信者のアドレス 22 | 送信者名 23 | メールはこのアドレスから来たものとして表示されます 24 | 暗号化 25 | キューにあるメールを今すぐ送信 26 | %d の送信待機中のメールがあります 27 | エラー 28 | このオプションを設定してください: 29 | 本文または件名を取得できませんでした。空のメールは送信されません。 30 | 認証に失敗しました。ユーザー名とパスワードを確認してください! 31 | サーバーが次のエラーを返しました。SMTP の設定を確認してください。 32 | インターネットの接続が見つかりませんでした。接続を確立して、もう一度試してください。 33 | サーバーの SSL 証明書が、お使いの Android システムによって信頼されていません。証明書をインポートして、もう一度試してください。 34 | パスワードを復号化できませんでした。別のデバイスにアプリを移動しましたか? 設定で、再度パスワードを入力してください。 35 | 残念ながら、この機能は BlitzMail Pro でのみ利用可能です。すべての機能を使用するために、そしてこのアプリの開発をサポートするために、このバージョンを入手してください。 36 | メールサーバーへの接続がタイムアウトしました。後でもう一度試すか、SMTP の設定を確認してください。 37 | サポートされていない方法で BlitzMail を呼び出しました。何を行ってこれを引き起したかを、開発者に報告してください! 38 | メールの添付ファイルを取得できません。 39 | ファイルが見つかりません! メールを送信しようとしてから、削除されていませんか? 40 | 必要なアクセス許可がないためメールを送信できませんでした。 41 | ファイルにアクセスする権限がありません。 設定でアクセス許可を与えてください! 42 | インターフェイス 43 | メール送信済の通知を表示 44 | メールが送信された後、ステータスバーに通知を表示します 45 | メールが送信された後、ステータスバーに通知を表示しません 46 | ファイルを共有 47 | 保存 48 | 送信するものはありません 49 | 50 | -------------------------------------------------------------------------------- /res/values-kab/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Azen 4 | Imayl yuznen 5 | Tuzna n BlitzMail 6 | Tuzna tettedu rǧu... 7 | Ɛreḍ tikelt nniḍen 8 | Azen ticki 9 | Anef 10 | Tuzna 11 | Iɣewwaṛen n uqeddac n yimayl 12 | Aqeddac ur yesri ara asesteb 13 | Aqeddac yesra asesteb 14 | Aqeddac SMTP 15 | Tabburt SMTP 16 | Asesteb SMTP 17 | Isem n useqdac 18 | Awal uffir 19 | Imaynt ara yettwaznen ar tensa-agi 20 | Tansa n unermis 21 | Tansa n umazan 22 | Isem n umazan 23 | Imaylen ara d-ibanen d akken kkan-d si tensa-a 24 | Awgelhen 25 | Azin tura imaylen yettraǧun 26 | Llan %d n yimaylen ayettraǧun tuzna 27 | Tuccḍa 28 | Sbadu asefran-agi: 29 | Ur d-yewwi tafekka neɣ asentel. Izen ur yettwazen ara acku yettban d ilem. 30 | Asesteb yecceḍ. Senqed isem-ik n useqdac neɣ awal uffir! 31 | Aqeddac yerra-d tuccḍa-agi. Senqed iɣewwaren-ik SMTP. 32 | Ulac tuqqna ar Internet. Qqen sakin ɛreḍ tikelt nniḍen. 33 | Aselkin SSL n uqeddac-ik ur yettwaman ara deg unagraw Android. Kter aselkin sakin ɛreḍ tikelt nniḍen. 34 | Ur izmir ara ad ikkes awgelhen n wawal-ik uffir. Tewwiḍ asnas ar yibenk-nniḍen? Ma ulac aɣilif sekcem awal-ik uffir deg iɣewwaṛen. 35 | Ad nesḥissef, imi tamahilt-agi tella kan di BlitzMail Pro. Ma ulac aɣilif awi lqem-agi akken ad tesqedceḍ akk timahilin udiq ad tmudded afus i tneflit n usnas-agi. 36 | Tuqqna ar uqeddac n yimayl tezri. Ɛreḍ tikelt nniḍen neɣ senqed iɣewwaṛen-ik SMTP. 37 | Abrid ur yettusefraken ara deg usiwel BlitzMail. Ma ulac aɣilif, azen amek i d-yeḍra waya i yineflayen! 38 | Ur izmir ara ad iseddu afaylu def imayl. 39 | Afaylu ulac-it! Ahat yettwakkes imi tɛreḍeḍ ad tazneḍ imayl? 40 | Ur izmir ara ad yazen imayl mar tasiregt ilaqen. 41 | Ur ɣur-k ara tasiregt akken ad tkecmeḍ ar ufaylu. Ma ulac aɣilif mudd tasiregt deg iɣewwaṛen! 42 | Agrudem 43 | Sken alɣu i yimail yuznen 44 | Sken-d ilɣa deg ufeggag n waddad seld tuzna n yimayl 45 | Ur d-skan ara ilɣa deg ufeggag n waddad seld tuzna n yimayl 46 | Afaylu(i-a) yebḍan d 47 | Sekles 48 | Ulac ayen ara tazneḍ 49 | 50 | -------------------------------------------------------------------------------- /res/values-nb/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Send 4 | Sendt e-post 5 | Sender Blitz-e-post 6 | Sender... 7 | Prøv igjen 8 | Send senere 9 | Avslå 10 | Sender 11 | Tjenerinnstillinger for e-post 12 | Tjeneren krever ikke bekreftelse 13 | Tjeneren krever bekreftelse 14 | SMTP-tjener 15 | SMTP-port 16 | SMTP-bekreft. 17 | Brukernavn 18 | Passord 19 | E-poster vil bli sendt til denne adressen 20 | Mottakers adresse 21 | Avsenders adresse 22 | Avsenders adresse 23 | E-poster vil tilsynelatende komme fra denne adressen 24 | Kryptering 25 | Send e-postene oppsamlingskø nå 26 | %d meldinger står i sendingskø 27 | Feil 28 | Ta dette valget: 29 | Fikk ikke kroppsfelt eller emnetittel. E-post ble sendt fordi det kan hende den er tom. 30 | Bekreftelse feilet. Sjekk brukernavn og passord. 31 | Tjeneren svarte med følgende feilmelding. Sjekk dine SMTP-innstillinger. 32 | Ingen internettilkobling. Tilsørg sådan, og prøv igjen. 33 | Din tjeners SSL-sertifikat ble ikke betrodd av ditt Android-system. Importer sertifikatet og prøv igjen. 34 | Kunne ikke dekryptere passordet ditt. Flyttet du programmet til en annen enhet? Før opp passordet ditt i innstillingene. 35 | Beklageligvis er dette trekkplasteret bare tilgjengelig i BlitzMail Pro. Installer denne hvis du vil ha fullversjon. Du støtter da utviklingen av programmet. 36 | Tidsavbrudd for tilkobling til e-posttjeneren. Prøv igjen senere eller sjekk SMTP-innstillingene. 37 | Kan ikke påkalle BlitzMail på denne måten. Si ifra om hva du gjorde for å framprovosere denne adferden til utvikleren. 38 | Kunne ikke innhente e-postens vedlegg. 39 | Fant ikke fila. Kanskje den har blitt slettet etter at du prøvde å sende e-posten? 40 | Kunne ikke sende e-post uten påkrevd tilgang. 41 | Du har ikke tilgang til denne fila. Gi filtilgang i innstillingene! 42 | Grensesnitt 43 | Vis merknad for sendt e-post 44 | Vis merknad i statusfeltet etter at e-posten har blitt sendt 45 | Ikke vis merknader i statusfeltet etter at e-post har blitt sendt. 46 | Fil(er) delt med 47 | Lagre 48 | Ingenting å sende 49 | 50 | -------------------------------------------------------------------------------- /res/values-nl/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Versturen 4 | E-mail versturen 5 | Bezig met versturen van BlitzMail... 6 | Bezig met versturen, even geduld... 7 | Opnieuw proberen 8 | Later versturen 9 | Afbreken 10 | Bezig met versturen... 11 | Mailserver-instellingen 12 | Server vereist geen authenticatie 13 | Server vereist authenticatie 14 | SMTP-server 15 | SMTP-poort 16 | SMTP-authenticatie 17 | Gebruikersnaam 18 | Wachtwoord 19 | E-mails worden verstuurd naar dit adres 20 | Adres van ontvanger 21 | Adres van afzender 22 | Naam van afzender 23 | E-mails zullen worden verstuurd vanaf dit e-mailadres 24 | Versleuteling 25 | E-mails in wachtrij nu versturen 26 | Er staat %d e-mail klaar voor verzending in de wachtrij 27 | Fout 28 | Stel deze optie in: 29 | Geen inhoud of onderwerp aangetroffen. De e-mail kan niet leeg worden verstuurd. 30 | Authenticatie mislukt. Controleer je gebruikersnaam en wachtwoord! 31 | De server gaf de volgende foutmelding: controleer je SMTP-instellingen. 32 | Geen internetverbinding. Maak verbinding met het internet en probeer het opnieuw. 33 | Het SSL-certificaat van je server wordt niet vertrouwd door je Android-systeem. Importeer het certificaat en probeer het opnieuw 34 | Je wachtwoord kan niet worden ontcijferd. Heb je de app verplaatst naar een ander apparaat? Voer je wachtwoord opnieuw in in de instellingen. 35 | Deze functie is alleen beschikbaar in BlitzMail Pro. Download deze versie om gebruik te kunnen maken van alle functies en de ontwikkeling van de app te ondersteunen. 36 | De verbinding met de mailserver is verlopen. Probeer het later opnieuw of controleer je SMTP-instellingen. 37 | Niet-ondersteunde methode van het oproepen van BlitzMail. Rapporteer dit aan de ontwikkelaar! 38 | De bijlage kan niet worden opgehaald. 39 | Bestand niet gevonden! Misschien is het verwijderd sinds het moment dat je de mail probeerde te versturen? 40 | E-mails kunnen niet worden verstuurd zonder vereiste machtiging. 41 | Geen toegang tot het bestand! Verleen machtiging in de instellingen! 42 | Uiterlijk 43 | Melding tonen voor verstuurde e-mails 44 | Melding tonen in statusbalk na versturen van e-mails 45 | Geen melding tonen in statusbalk na het versturen van e-mails 46 | Bestand(en) gedeeld met 47 | Opslaan 48 | Er valt niks te versturen 49 | 50 | -------------------------------------------------------------------------------- /res/values-pl/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Wyślij 4 | Wyślij wiadomość 5 | Wysyłanie BlitzMail-a 6 | Wysyłanie, proszę czekać... 7 | Spróbuj ponownie 8 | Wyślij później 9 | Odrzuć 10 | Wysyłanie 11 | Ustawienia serwera poczty 12 | Serwer nie wymaga uwierzytelnienia 13 | Serwer wymaga uwierzytelnienia 14 | Serwer SMTP 15 | Port SMTP 16 | SMTP Auth 17 | Nazwa użytkownika 18 | Hasło 19 | Wiadomości zostaną wysłane na ten adres 20 | Adres odbiorcy 21 | Adres nadawcy 22 | Nazwa nadawcy 23 | Wiadomości zostaną wysłane z tego adresu 24 | Szyfrowanie 25 | Wyślij teraz zakolejkowane wiadomości 26 | %d wiadomości oczekuje na przesłanie 27 | Błąd 28 | Proszę ustawić tę opcję: 29 | Nie ma ani tematu, ani treści wiadomości. Pusta wiadomość nie zostanie wysłana. 30 | Błąd uwierzytelniania. Sprawdź nazwę użytkownika i hasło! 31 | Serwer zwrócił następujący błąd. Sprawdź ustawienia serwera SMTP. 32 | Brak połączenia z Internetem. Połącz się z siecią i spróbuj ponownie. 33 | Certyfikat SSL Twojego serwera jest nie jest zaufany w systemie Android. Zaimportuj certyfikat i spróbuj ponownie. 34 | Nie można odszyfrować hasła. Może przeniosłeś aplikację z innego urządzenia? Wpisz ponownie swoje hasło w ustawieniach. 35 | Niestety ta funkcja jest możliwa tylko w BlitzMail Pro. Pobierz tę wersję aby uzyskać dostęp do wszystkich funkcji i wesprzeć rozwój programu. 36 | Przekroczono czas oczekiwania na połączenie z serwerem poczty. Spróbuj ponownie później, lub sprawdź ustawienia SMTP. 37 | Niewspierany sposób wywołania programu BlitzMail. Prosimy skontaktować się z twórcą programu i opisać co spowodowało błąd! 38 | Problem dołączania załącznika do wiadomości. 39 | Nie znaleziono pliku! Może został on usunięty przed próbą wysłania wiadomości? 40 | Nie można wysłać wiadomości bez wymaganego zezwolenia. 41 | Nie masz zezwolenia na dostęp do pliku. Udziel zezwolenia w ustawieniach! 42 | Interfejs 43 | Pokaż powiadomienia wysłanych wiadomości 44 | Pokaż powiadomienie na belce powiadomień po każdej wysłanej wiadomości 45 | Nie pokazuj powiadomień na belce powiadomień po każdej wysłanej wiadomości 46 | Plik(i) wysłane przez 47 | Zapisz 48 | Nie ma nic do wysłania 49 | 50 | -------------------------------------------------------------------------------- /res/values-pt-rBR/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Enviar 4 | Email Enviado 5 | Enviando BlitzMail 6 | Enviando, por favor aguarde... 7 | Tente Novamente 8 | Enviar mais Tarde 9 | Dispensar 10 | Enviando 11 | Configuração do servidor de Email 12 | O servidor não requer autenticação 13 | O servidor requer autenticação 14 | Servidor SMTP 15 | Porta SMTP 16 | Autenticação SMTP 17 | Nome de Usuário 18 | Senha 19 | Emails serão enviados para este endereço 20 | Endereço do Destinatário 21 | Endereço do Remetente 22 | Nome do Remetente 23 | Emails serão mostrados vindo deste endereço 24 | Encriptação 25 | Enviar emails na fila de espera Agora 26 | Existem %d emails aguardando para serem enviados 27 | Erro 28 | Por favor, defina esta opção: 29 | Não obteve o conteúdo ou assunto. O email não foi enviado porque seria vazio. 30 | Falha na Autenticação. Por favor, cheque seu nome de usuário e senha! 31 | O servidor retornou o erro seguinte. Por favor, cheque suas configurações de SMTP. 32 | Sem conexão com a Internet. Por favor, estabeleça a conectividade e tente novamente. 33 | O certificato SSL do seu servidor não é tido como confiável pelo seu sistema Android. Por favor, importe o certificado e tente novamente. 34 | Não foi possível desencriptar a sua senha. Você moveu o aplicativo para outro aparelho? Por favor, entre sua senha novamente nas configurações. 35 | Infelizmente, esse recurso está disponível somente no BlitzMail Pro. Por favor, obtenha esta versão para usar todos os recursos e apoiar o desenvolvimento deste aplicativo. 36 | A conexão com o servidor de email expirou. Por favor, tente novamente mais tarde ou verifique suas configurações de SMTP. 37 | Forma não suportada de chamar o BlitzMail. Por favor, reporte ao desenvolvedor o que você fez para que isto ocorresse. 38 | Não foi possível obter o anexo para o email. 39 | Arquivo não encontrado. Talvez tenha sido excluído desde que você tentou enviar o email? 40 | Não foi possível enviar o email sem a permissão requerida. 41 | Não tem permissão para acessar arquivos. Por favor, vá até configurações e conceda a permissão! 42 | Interface 43 | Mostrar Notificação para emails Enviados 44 | Mostrar notificação na barra de status após o email ser enviado 45 | Não mostrar notificação na barra de status após o email ser enviado 46 | Arquivo(s) compartilhados com 47 | Salvar 48 | Nada para enviar 49 | 50 | -------------------------------------------------------------------------------- /res/values-pt-rPT/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Enviar 4 | Email Enviado 5 | A Enviar BlitzMail 6 | A enviar, por favor aguarde... 7 | Tente Novamente 8 | Enviar mais Tarde 9 | Dispensar 10 | A enviar 11 | Configuração do servidor de Email 12 | O servidor não requer autenticação 13 | O servidor requer autenticação 14 | Servidor SMTP 15 | Porta SMTP 16 | Autenticação SMTP 17 | Nome de Utilizador 18 | Palavra-Chave 19 | Os emails serão enviados para este endereço 20 | Endereço do Destinatário 21 | Endereço do Remetente 22 | Nome do Remetente 23 | Os emails terão como remetente este endereço 24 | Encriptação 25 | Enviar emails na fila de espera Agora 26 | Existem %d emails a aguardar o envio 27 | Erro 28 | Por favor, defina esta opção: 29 | Não obteve o conteúdo ou assunto. O email não foi enviado porque está vazio. 30 | Falha na autenticação. Por favor, verifique o seu nome de utilizador e a palavra-chave! 31 | O servidor devolveu o seguinte erro. Por favor, verifique as suas configurações de SMTP. 32 | Sem ligação à Internet. Por favor, verifique a ligação e tente novamente. 33 | O certificado SSL do seu servidor não é tido como confiável pelo seu sistema Android. Por favor, faça a importação do certificado e tente novamente. 34 | Não foi possível desencriptar a sua palavra-chave. Movimentou a aplicação para outro dispositivo? Por favor, introduza novamente a sua palavra-chave nas configurações. 35 | Infelizmente, este recurso está disponível somente no BlitzMail Pro. Por favor, obtenha essa versão para usar todos os recursos e apoiar o desenvolvimento desta aplicação. 36 | A ligação ao servidor de email ultrapassou o tempo de resposta. Por favor, tente novamente mais tarde ou verifique as configurações de SMTP. 37 | Forma de chamar o BlitzMail não suportada. Por favor, reporte ao programador o que fez para que isto acontecesse. 38 | Não foi possível obter o anexo para o email. 39 | Ficheiro não encontrado. Talvez tenha sido eliminado enquanto tentava enviar o email? 40 | Não foi possível enviar o email sem a permissão necessária. 41 | Não tem permissão para aceder ao ficheiro. Por favor, altere nas configurações a cedência da permissão! 42 | Interface 43 | Mostrar Notificação para emails Enviados 44 | Mostrar notificação na barra de estado após o email ser enviado 45 | Não mostrar notificação na barra de estado após o email ser enviado 46 | Ficheiro(s) partilhados com 47 | Gravar 48 | Nada para enviar 49 | 50 | -------------------------------------------------------------------------------- /res/values-tr/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Gönder 4 | Gönderilen Posta 5 | BlitzMail Gönderiliyor 6 | Gönderiliyor lütfen bekleyin... 7 | Tekrar Dene 8 | Daha Sonra Gönder 9 | İptal Et 10 | Gönderiliyor 11 | Posta Sunucusu Ayarları 12 | Sunucu kimlik doğrulaması gerektirmiyor 13 | Sunucu kimlik doğrulaması gerektiriyor 14 | SMTP Sunucusu 15 | SMTP Portu 16 | SMTP Kimlik Doğrulaması 17 | Kullanıcı Adı 18 | Şifre 19 | Postalar bu adrese gönderilecek 20 | Alıcı Adresi 21 | Gönderici Adresi 22 | Gönderici Adı 23 | Postalar bu adresten gelmiş görünecek 24 | Şifreleme 25 | Kuyruğa Eklenmiş Postaları Şimdi Gönder 26 | Gönderilmeyi bekleyen %d posta var 27 | Hata 28 | Lütfen bu seçeneği ayarlayın: 29 | Gövde yada başlığı alamadı. Posta gönderilemedi çünkü boş olabilir. 30 | Kimlik doğrulama başarısız oldu. Lütfen kullanıcı adı ve şifrenizi kontrol edin! 31 | Sunucu ilgili hatayı döndürdü. Lütfen SMTP ayarlarını denetleyiniz. 32 | İnternet bağlantısı bulunamadı. Lütfen bağlantıyı sağlayınız ve yeniden deneyiniz 33 | Sunucunuzun SSL sertifikası Android sisteminiz tarafından güvenilmiyor. Lütfen sertifikayı içeri aktarın ve tekrar deneyin. 34 | Şifreniz çözülemedi. Uygulamayı farklı bir cihaza mı aktardınız? Lütfen şifrenizi ayarlarda tekrar giriniz. 35 | Ne yazık ki bu özellik sadece BlitzMail Pro\'da bulunmaktadır. Lütfen tum özellikleri kullanabilmek ve bu uygulamanın gelişimini desteklemek için bu versiyonu alınız. 36 | Posta sunucusu bağlantısı zaman aşımına uğradı. Lütfen daha sonra tekrar deneyiniz yada SMTP ayarlarınızı denetleyiniz. 37 | BlitzMail\'in çağırılması bu yolla desteklenmemektedir. Lütfen geliştiriciye buna neden olanı bildiriniz! 38 | Mail için ek dosya alınamadı. 39 | Dosya bulunamadı! Postayı göndermeye çalışırken silinmiş olabilir? 40 | Gerekli izin olmadan posta gönderilemedi. 41 | Dosyaya erişim için izin bulunmamaktadır. Lütfen izni ayarlardan sağlayınız! 42 | Arayüz 43 | Posta Gönder için Bildirimleri Göster 44 | Postanın gönderilmesinden sonra durum çubuğunda bildirim göster 45 | Postanın gönderilmesinden sonra durum çubuğunda bildirim gösterme 46 | Paylaşılan dosya(lar) 47 | Kaydet 48 | Gönderilecek bir şey yok 49 | 50 | -------------------------------------------------------------------------------- /res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | None 7 | STARTTLS 8 | SSL 9 | 10 | 11 | 12 | none 13 | tls 14 | ssl 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #fff4b94b 5 | #ffd69d45 6 | #fff4b94b 7 | 8 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BlitzMail 5 | BlitzNote 6 | Send 7 | Sent Mail 8 | Sending BlitzMail 9 | Sending please wait… 10 | "Try Again" 11 | "Send Later" 12 | "Dismiss" 13 | Delete 14 | Sending 15 | Mail Server Settings 16 | Server does not require authentication 17 | Server requires authentication 18 | SMTP Server 19 | SMTP Port 20 | SMTP Auth 21 | Username 22 | Password 23 | Mails will be send to this address 24 | Recipient Address 25 | Sender Address 26 | Sender Name 27 | Mails will appear to come from this address 28 | Encryption 29 | Send Queued Mails Now 30 | There is %d mails waiting to be sent 31 | Error 32 | Please set this option: 33 | Did not get body or subject. Mail not send because it would be empty. 34 | Authentication failed. Please check your username and password! 35 | The server returned the following error. Please check your SMTP settings. 36 | No connection to the internet found. Please establish connectivity and try again. 37 | Your server\'s SSL certificate is not trusted by your Android system. Please import the certificate and try again. 38 | Could not decrypt your password. Did you move the app to another device? Please enter your password again in the settings. 39 | Unfortunately, this feature is only available in BlitzMail Pro. Please get this version to use all features and to support the development of this app. 40 | The connection to the mail server timed out. Please try again later or check your SMTP settings. 41 | Unsupported way of calling BlitzMail. Please report what you did to cause this to the developer! 42 | Could not get attachment for mail. 43 | File not found! Maybe it has been deleted since you tried to send the mail? 44 | Could not send mail without required permission. 45 | Don\'t have permission to access file. Please grant permission in settings! 46 | Interface 47 | Show Notification for Sent Mail 48 | Show notification in status bar after mail has been sent 49 | Don\'t show notification in status bar after mail has been sent 50 | File(s) shared with 51 | Save 52 | Nothing to send 53 | Mail will be send when online 54 | 55 | -------------------------------------------------------------------------------- /res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /res/xml/preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 13 | 14 | 19 | 23 | 24 | 25 | 26 | 29 | 30 | 34 | 39 | 44 | 50 | 54 | 59 | 60 | 61 | 62 | 65 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/com/provider/JSSEProvider.java: -------------------------------------------------------------------------------- 1 | package com.provider; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | /** 21 | * @author Alexander Y. Kleymenov 22 | * @version $Revision$ 23 | */ 24 | 25 | 26 | import java.security.AccessController; 27 | import java.security.Provider; 28 | 29 | public final class JSSEProvider extends Provider { 30 | 31 | /** 32 | * 33 | */ 34 | private static final long serialVersionUID = 7755072811450929515L; 35 | 36 | public JSSEProvider() { 37 | super("HarmonyJSSE", 1.0, "Harmony JSSE Provider"); 38 | AccessController.doPrivileged(new java.security.PrivilegedAction() { 39 | public Void run() { 40 | put("SSLContext.TLS", "org.apache.harmony.xnet.provider.jsse.SSLContextImpl"); 41 | put("Alg.Alias.SSLContext.TLSv1", "TLS"); 42 | put("KeyManagerFactory.X509", "org.apache.harmony.xnet.provider.jsse.KeyManagerFactoryImpl"); 43 | put("TrustManagerFactory.X509", "org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl"); 44 | return null; 45 | } 46 | }); 47 | } 48 | } -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/MailStorage.java: -------------------------------------------------------------------------------- 1 | /* BlitzMail 2 | * Copyright (C) 2013 Torsten Grote 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program 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 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package de.grobox.blitzmail; 19 | 20 | import android.annotation.SuppressLint; 21 | import android.content.Context; 22 | import android.content.SharedPreferences; 23 | import android.util.Log; 24 | 25 | import org.json.JSONArray; 26 | import org.json.JSONException; 27 | import org.json.JSONObject; 28 | 29 | import java.io.File; 30 | 31 | import static android.content.Context.MODE_PRIVATE; 32 | 33 | public class MailStorage { 34 | 35 | public static JSONObject getMails(Context context) { 36 | SharedPreferences sharedPref = context.getSharedPreferences("BlitzMail", MODE_PRIVATE); 37 | String mails_str = sharedPref.getString("mails", null); 38 | 39 | JSONObject mails = new JSONObject(); 40 | 41 | if(mails_str != null) { 42 | try { 43 | mails = new JSONObject(mails_str); 44 | } catch (JSONException e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | 49 | return mails; 50 | } 51 | 52 | @SuppressLint("ApplySharedPref") 53 | public static synchronized void saveMail(Context context, JSONObject mail) { 54 | SharedPreferences sharedPref = context.getSharedPreferences("BlitzMail", MODE_PRIVATE); 55 | SharedPreferences.Editor prefEditor = sharedPref.edit(); 56 | 57 | JSONObject mails = getMails(context); 58 | 59 | try { 60 | mails.put(mail.getString("id"), mail); 61 | } catch (JSONException e) { 62 | throw new AssertionError(e); 63 | } 64 | 65 | prefEditor.putString("mails", mails.toString()); 66 | prefEditor.commit(); // save this right away 67 | } 68 | 69 | public static synchronized void deleteMail(Context context, String id) { 70 | SharedPreferences sharedPref = context.getSharedPreferences("BlitzMail", MODE_PRIVATE); 71 | SharedPreferences.Editor prefEditor = sharedPref.edit(); 72 | 73 | JSONObject mails = getMails(context); 74 | 75 | // also delete temporary file 76 | try { 77 | if(mails.getJSONObject(id).has("attachments")) { 78 | JSONArray attachments = mails.getJSONObject(id).getJSONArray("attachments"); 79 | 80 | // iterate over all attachments 81 | for(int i = 0; i < attachments.length(); i++) { 82 | JSONObject attachment = attachments.getJSONObject(i); 83 | 84 | File file = new File(attachment.getString("path")); 85 | file.delete(); 86 | } 87 | } 88 | } catch(JSONException e) { 89 | e.printStackTrace(); 90 | } 91 | 92 | // remove actual email 93 | mails.remove(id); 94 | 95 | String mails_str = null; 96 | try { 97 | mails_str = mails.toString(4); 98 | } catch (JSONException e) { 99 | e.printStackTrace(); 100 | } 101 | 102 | Log.d("MailStorage", "Removing mail with id " + id); 103 | 104 | prefEditor.putString("mails", mails_str); 105 | prefEditor.apply(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/MainActivity.kt: -------------------------------------------------------------------------------- 1 | /* BlitzMail 2 | * Copyright (C) 2013 Torsten Grote 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program 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 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package de.grobox.blitzmail 19 | 20 | import android.os.Bundle 21 | import android.view.MenuItem 22 | import androidx.appcompat.app.AppCompatActivity 23 | import de.grobox.blitzmail.preferences.PrefFragment 24 | 25 | class MainActivity : AppCompatActivity() { 26 | 27 | override fun onCreate(savedInstanceState: Bundle?) { 28 | super.onCreate(savedInstanceState) 29 | 30 | setContentView(R.layout.activity_main) 31 | 32 | val actionBar = supportActionBar 33 | actionBar?.setDisplayHomeAsUpEnabled(true) 34 | 35 | if (savedInstanceState == null) { 36 | fragmentManager 37 | .beginTransaction() 38 | .add(R.id.container, PrefFragment()) 39 | .commit() 40 | } 41 | } 42 | 43 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 44 | return if (item.itemId == android.R.id.home) { 45 | onBackPressed() 46 | true 47 | } else { 48 | false 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/NoteActivity.java: -------------------------------------------------------------------------------- 1 | /* BlitzMail 2 | * Copyright (C) 2013 Torsten Grote 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program 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 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package de.grobox.blitzmail; 19 | 20 | import android.app.Dialog; 21 | import android.content.ClipData; 22 | import android.content.ClipboardManager; 23 | import android.content.DialogInterface; 24 | import android.content.Intent; 25 | import android.content.SharedPreferences; 26 | import android.os.Bundle; 27 | import androidx.appcompat.app.AlertDialog; 28 | import androidx.appcompat.app.AppCompatActivity; 29 | import de.grobox.blitzmail.send.SendActivity; 30 | 31 | import android.view.View; 32 | import android.view.ViewGroup; 33 | import android.view.Window; 34 | import android.view.WindowManager; 35 | import android.widget.EditText; 36 | import android.widget.Toast; 37 | 38 | public class NoteActivity extends AppCompatActivity { 39 | 40 | private EditText textView; 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | 46 | View mView = getLayoutInflater().inflate(R.layout.activity_note, null); 47 | textView = (EditText) mView.findViewById(R.id.text); 48 | 49 | AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.DialogTheme) 50 | .setView(mView) 51 | .setTitle(R.string.note_name) 52 | .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { 53 | public void onClick(DialogInterface dialog, int id) { 54 | dialog.cancel(); 55 | } 56 | }) 57 | .setNeutralButton(R.string.save, new DialogInterface.OnClickListener() { 58 | public void onClick(DialogInterface dialog, int id) { 59 | finish(); 60 | } 61 | }) 62 | .setPositiveButton(R.string.send_mail, new DialogInterface.OnClickListener() { 63 | public void onClick(DialogInterface dialog, int id) { 64 | String msg = textView.getText().toString(); 65 | 66 | if (msg.trim().isEmpty()) { 67 | Toast.makeText(NoteActivity.this, R.string.warning_nothing_to_send, Toast.LENGTH_SHORT).show(); 68 | } else { 69 | sendMail(msg); 70 | textView.setText(""); 71 | } 72 | finish(); 73 | } 74 | }) 75 | .setOnCancelListener(new DialogInterface.OnCancelListener() { 76 | @Override 77 | public void onCancel(DialogInterface dialog) { 78 | textView.setText(""); 79 | finish(); 80 | } 81 | }); 82 | 83 | // Create the AlertDialog object and show it 84 | Dialog dialog = builder.create(); 85 | dialog.setCanceledOnTouchOutside(false); 86 | dialog.show(); 87 | 88 | // stretch horizontally across screen 89 | Window window = dialog.getWindow(); 90 | window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); 91 | 92 | // Open keyboard 93 | dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); 94 | } 95 | 96 | @Override 97 | protected void onResume() { 98 | super.onResume(); 99 | 100 | // restore note if there is one to restore 101 | SharedPreferences prefs = getPreferences(MODE_PRIVATE); 102 | String savedNote = prefs.getString("note", null); 103 | 104 | if (savedNote != null && !savedNote.isEmpty()) { 105 | // pre-fill with saved note 106 | textView.setText(savedNote); 107 | textView.setSelection(prefs.getInt("selStart", 0), prefs.getInt("selEnd", 0)); 108 | } else { 109 | // pre-fill with clipboard content note 110 | ClipData clip = ((ClipboardManager)getSystemService(CLIPBOARD_SERVICE)).getPrimaryClip(); 111 | if (clip != null) { 112 | String text = clip.getItemAt(0).getText().toString(); 113 | if (!text.isEmpty()) { 114 | // only pre-fill a particular clipboard content once 115 | int lastClip = text.hashCode(); 116 | if (lastClip != prefs.getInt("lastClip", 0)) { 117 | textView.setText(text); 118 | textView.selectAll(); 119 | // we use the hashcode to avoid storing sensitive data 120 | prefs.edit().putInt("lastClip", lastClip).apply(); 121 | } 122 | } 123 | } 124 | } 125 | } 126 | 127 | @Override 128 | protected void onPause() { 129 | super.onPause(); 130 | 131 | // save note in case app gets killed 132 | SharedPreferences.Editor prefs = getPreferences(MODE_PRIVATE).edit(); 133 | prefs.putString("note", textView.getText().toString()); 134 | prefs.putInt("selStart", textView.getSelectionStart()); 135 | prefs.putInt("selEnd", textView.getSelectionEnd()); 136 | prefs.apply(); 137 | } 138 | 139 | private void sendMail(CharSequence text) { 140 | Intent intent = new Intent(this, SendActivity.class); 141 | intent.setAction(Intent.ACTION_SEND); 142 | intent.setType("text/plain"); 143 | intent.putExtra(Intent.EXTRA_TEXT, text); 144 | 145 | startActivity(intent); 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/PrivateConstants.sample_java: -------------------------------------------------------------------------------- 1 | package de.grobox.blitzmail; 2 | 3 | public interface PrivateConstants { 4 | public static final char[] CryptoKey = "[Please insert your encryption key here]".toCharArray(); 5 | } 6 | -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/crypto/Crypto.java: -------------------------------------------------------------------------------- 1 | package de.grobox.blitzmail.crypto; 2 | 3 | import android.content.Context; 4 | import android.provider.Settings; 5 | import android.util.Base64; 6 | 7 | import javax.crypto.Cipher; 8 | import javax.crypto.SecretKey; 9 | import javax.crypto.SecretKeyFactory; 10 | import javax.crypto.spec.PBEKeySpec; 11 | import javax.crypto.spec.PBEParameterSpec; 12 | 13 | import static de.grobox.blitzmail.PrivateConstants.CryptoKey; 14 | 15 | public class Crypto { 16 | 17 | private Context context; 18 | private static final String UTF8 = "utf-8"; 19 | 20 | public Crypto(Context context) { 21 | this.context = context; 22 | } 23 | 24 | String encrypt( String value ) { 25 | try { 26 | final byte[] bytes = value!=null ? value.getBytes(UTF8) : new byte[0]; 27 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); 28 | SecretKey key = keyFactory.generateSecret(new PBEKeySpec(CryptoKey)); 29 | Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES"); 30 | pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(Settings.Secure.getString(context.getContentResolver(),Settings.System.ANDROID_ID).getBytes(UTF8), 20)); 31 | return new String(Base64.encode(pbeCipher.doFinal(bytes), Base64.NO_WRAP),UTF8); 32 | 33 | } catch( Exception e ) { 34 | throw new RuntimeException(e); 35 | } 36 | 37 | } 38 | 39 | public String decrypt(String value){ 40 | try { 41 | final byte[] bytes = value!=null ? Base64.decode(value,Base64.DEFAULT) : new byte[0]; 42 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); 43 | SecretKey key = keyFactory.generateSecret(new PBEKeySpec(CryptoKey)); 44 | Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES"); 45 | pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(Settings.Secure.getString(context.getContentResolver(),Settings.System.ANDROID_ID).getBytes(UTF8), 20)); 46 | return new String(pbeCipher.doFinal(bytes),UTF8); 47 | 48 | } catch( Exception e) { 49 | throw new RuntimeException(e); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/crypto/EncryptedEditTextPreference.java: -------------------------------------------------------------------------------- 1 | package de.grobox.blitzmail.crypto; 2 | 3 | import android.content.Context; 4 | import android.preference.EditTextPreference; 5 | import android.util.AttributeSet; 6 | 7 | public class EncryptedEditTextPreference extends EditTextPreference { 8 | 9 | private Crypto crypto; 10 | 11 | public EncryptedEditTextPreference(Context context, AttributeSet attrs, int defStyle) { 12 | super(context, attrs, defStyle); 13 | crypto = new Crypto(context); 14 | } 15 | 16 | public EncryptedEditTextPreference(Context context, AttributeSet attrs) { 17 | super(context, attrs); 18 | crypto = new Crypto(context); 19 | } 20 | 21 | public EncryptedEditTextPreference(Context context) { 22 | super(context); 23 | crypto = new Crypto(context); 24 | } 25 | 26 | @Override 27 | public String getText() { 28 | String value = super.getText(); 29 | if(value == null) { 30 | return null; 31 | } else { 32 | try { 33 | return crypto.decrypt(value); 34 | } 35 | catch(Exception e) { 36 | return null; 37 | } 38 | } 39 | } 40 | 41 | @Override 42 | protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { 43 | super.setText(restoreValue ? getPersistedString(null) : (String) defaultValue); 44 | } 45 | 46 | @Override 47 | public void setText(String text) { 48 | if(text == null) { 49 | super.setText(null); 50 | return; 51 | } 52 | super.setText(crypto.encrypt(text)); 53 | } 54 | } -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/notification/MailNotificationManager.kt: -------------------------------------------------------------------------------- 1 | package de.grobox.blitzmail.notification 2 | 3 | import android.annotation.SuppressLint 4 | import android.app.Notification 5 | import android.app.NotificationChannel 6 | import android.app.NotificationManager 7 | import android.app.NotificationManager.IMPORTANCE_LOW 8 | import android.app.PendingIntent 9 | import android.app.PendingIntent.FLAG_UPDATE_CURRENT 10 | import android.content.Context 11 | import android.content.Context.NOTIFICATION_SERVICE 12 | import android.content.Intent 13 | import android.content.Intent.FLAG_ACTIVITY_NEW_TASK 14 | import android.graphics.BitmapFactory 15 | import android.os.Build 16 | import android.preference.PreferenceManager 17 | import androidx.core.app.NotificationCompat 18 | import de.grobox.blitzmail.R 19 | import de.grobox.blitzmail.notification.NotificationHandlerActivity.Companion.ACTION_DIALOG 20 | import de.grobox.blitzmail.notification.NotificationHandlerActivity.Companion.ACTION_FINISH 21 | import de.grobox.blitzmail.notification.NotificationHandlerActivity.Companion.ACTION_SEND_LATER 22 | import de.grobox.blitzmail.notification.NotificationHandlerActivity.Companion.EXTRA_MAIL_ID 23 | import java.security.cert.CertificateException 24 | import javax.crypto.BadPaddingException 25 | import javax.mail.AuthenticationFailedException 26 | import javax.mail.MessagingException 27 | import javax.net.ssl.SSLException 28 | 29 | 30 | @SuppressLint("StaticFieldLeak") 31 | private var mailNotificationManager: MailNotificationManager? = null 32 | 33 | /** 34 | * @param context pass only ApplicationContext here 35 | */ 36 | fun getMailNotificationManager(context: Context): MailNotificationManager { 37 | return mailNotificationManager ?: MailNotificationManager(context) 38 | } 39 | 40 | const val NOTIFICATION_ID_SENDING = 1 41 | const val NOTIFICATION_ID_ERROR = 2 42 | private const val NOTIFICATION_CHANNEL_ID = "BlitzMail" 43 | 44 | class MailNotificationManager internal constructor(val c: Context) { 45 | 46 | private val notificationManager = c.getSystemService(NOTIFICATION_SERVICE) as NotificationManager 47 | private val notificationBuilder = NotificationCompat.Builder(c, NOTIFICATION_CHANNEL_ID) 48 | 49 | fun createNotificationChannel() { 50 | if (Build.VERSION.SDK_INT >= 26) { 51 | val channel = NotificationChannel(NOTIFICATION_CHANNEL_ID, c.getString(R.string.app_name), IMPORTANCE_LOW) 52 | notificationManager.createNotificationChannel(channel) 53 | } 54 | } 55 | 56 | fun getForegroundNotification(): Notification { 57 | val notifyIntent = Intent(c, NotificationHandlerActivity::class.java) 58 | notifyIntent.flags = FLAG_ACTIVITY_NEW_TASK 59 | val pendingIntent = PendingIntent.getActivity(c, 0, notifyIntent, FLAG_UPDATE_CURRENT) 60 | 61 | return NotificationCompat.Builder(c, NOTIFICATION_CHANNEL_ID) 62 | .setContentTitle(c.getString(R.string.sending_mail)) 63 | .setContentText(c.getString(R.string.please_wait)) 64 | .setSmallIcon(R.drawable.notification_icon) 65 | .setLargeIcon(BitmapFactory.decodeResource(c.resources, R.drawable.ic_launcher)) 66 | // .setStyle(NotificationCompat.BigTextStyle().bigText(subject)) 67 | .setOngoing(true) 68 | .setProgress(0, 0, true) 69 | .setContentIntent(pendingIntent) 70 | .build() 71 | } 72 | 73 | fun showSuccessNotification(mailId: Int, subject: String?) { 74 | // set progress notification to finished 75 | notificationBuilder.setProgress(0, 0, false) 76 | notificationBuilder.setOngoing(false) 77 | 78 | // set dialog to auto close when clicked 79 | notificationBuilder.setAutoCancel(true) 80 | 81 | // check to see if there should be a success notification 82 | if (!PreferenceManager.getDefaultSharedPreferences(c).getBoolean("pref_success_notification", true)) { 83 | // don't show success notification 84 | notificationManager.cancel(mailId) 85 | return 86 | } 87 | 88 | val msg = subject ?: "" 89 | 90 | // show success notification 91 | notificationBuilder.setContentTitle(c.getString(R.string.sent_mail)) 92 | .setLargeIcon(BitmapFactory.decodeResource(c.resources, R.drawable.ic_launcher)) 93 | .setSmallIcon(R.drawable.ic_stat_notify) 94 | val notifyIntent = Intent(c, NotificationHandlerActivity::class.java) 95 | notifyIntent.flags = FLAG_ACTIVITY_NEW_TASK 96 | notifyIntent.action = ACTION_FINISH 97 | 98 | // Quick Action: Dismiss 99 | val piDismiss = PendingIntent.getActivity(c, 0, notifyIntent, FLAG_UPDATE_CURRENT) 100 | notificationBuilder.addAction(R.drawable.ic_action_cancel, c.getString(R.string.dismiss), piDismiss) 101 | 102 | // Update the notification 103 | notificationBuilder.setStyle(NotificationCompat.BigTextStyle().bigText(msg)) 104 | .setContentText(msg.substring(0, if (msg.length <= 32) msg.length else 32)) 105 | .setContentIntent(PendingIntent.getActivity(c, 0, notifyIntent, FLAG_UPDATE_CURRENT)) 106 | notificationManager.notify(mailId, notificationBuilder.build()) 107 | } 108 | 109 | fun showErrorNotification(e: Exception, mailId: String) { 110 | // set progress notification to finished 111 | notificationBuilder.setProgress(0, 0, false) 112 | notificationBuilder.setOngoing(false) 113 | 114 | // set notification to auto close when clicked 115 | notificationBuilder.setAutoCancel(true) 116 | 117 | // show error notification 118 | notificationBuilder.setContentTitle(c.getString(R.string.app_name) + " - " + c.getString(R.string.error)) 119 | .setLargeIcon(BitmapFactory.decodeResource(c.resources, R.drawable.ic_launcher)) 120 | .setSmallIcon(android.R.drawable.ic_dialog_alert) 121 | 122 | // Quick Action: Try Again 123 | val tryAgainIntent = Intent(c, NotificationHandlerActivity::class.java) 124 | tryAgainIntent.action = NotificationHandlerActivity.ACTION_TRY_AGAIN 125 | tryAgainIntent.flags = FLAG_ACTIVITY_NEW_TASK 126 | val piTryAgain = PendingIntent.getActivity(c, 0, tryAgainIntent, FLAG_UPDATE_CURRENT) 127 | notificationBuilder.addAction(R.drawable.ic_action_try_again, c.getString(R.string.try_again), piTryAgain) 128 | 129 | // Quick Action: Send Later 130 | val sendLaterIntent = Intent(c, NotificationHandlerActivity::class.java) 131 | sendLaterIntent.action = ACTION_SEND_LATER 132 | tryAgainIntent.flags = FLAG_ACTIVITY_NEW_TASK 133 | val piSendLater = PendingIntent.getActivity(c, 0, sendLaterIntent, FLAG_UPDATE_CURRENT) 134 | notificationBuilder.addAction(R.drawable.ic_action_send_later, c.getString(R.string.send_later), piSendLater) 135 | 136 | e.printStackTrace() 137 | 138 | var msg = if (e is AuthenticationFailedException) { 139 | c.getString(R.string.error_auth_failed) 140 | } else if (e is MessagingException && e.cause is SSLException && (e.cause as Exception).cause is CertificateException) { 141 | c.getString(R.string.error_sslcert_invalid) 142 | } else if (e is RuntimeException && e.cause is BadPaddingException) { 143 | c.getString(R.string.error_decrypt) 144 | } else { 145 | // TODO improve showing the error here 146 | c.getString(R.string.error_smtp) + '\n'.toString() + e.localizedMessage 147 | } 148 | 149 | // get and show the cause for the exception if it exists 150 | if (e.cause is Exception) { 151 | val cause = e.cause as Exception 152 | msg += "\nCause: " + cause.localizedMessage 153 | } 154 | 155 | val notifyIntent = Intent(c, NotificationHandlerActivity::class.java) 156 | notifyIntent.flags = FLAG_ACTIVITY_NEW_TASK 157 | notifyIntent.action = ACTION_DIALOG 158 | notifyIntent.putExtra("ContentTitle", c.getString(R.string.error)) 159 | notifyIntent.putExtra("ContentText", msg) 160 | notifyIntent.putExtra(EXTRA_MAIL_ID, mailId) 161 | 162 | // Update the notification 163 | notificationBuilder.setStyle(NotificationCompat.BigTextStyle().bigText(msg)) 164 | .setContentText(msg.substring(0, if (msg.length <= 32) msg.length else 32)) 165 | .setContentIntent(PendingIntent.getActivity(c, 0, notifyIntent, FLAG_UPDATE_CURRENT)) 166 | notificationManager.notify(NOTIFICATION_ID_ERROR, notificationBuilder.build()) 167 | } 168 | 169 | fun cancelErrorNotification() { 170 | notificationManager.cancel(NOTIFICATION_ID_ERROR) 171 | } 172 | 173 | } 174 | -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/notification/NotificationHandlerActivity.kt: -------------------------------------------------------------------------------- 1 | /* BlitzMail 2 | * Copyright (C) 2013 Torsten Grote 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program 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 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package de.grobox.blitzmail.notification 19 | 20 | import android.app.Activity 21 | import android.content.Intent 22 | import android.net.Uri 23 | import android.os.Bundle 24 | import androidx.appcompat.app.AlertDialog 25 | import de.grobox.blitzmail.BuildConfig 26 | import de.grobox.blitzmail.MailStorage 27 | import de.grobox.blitzmail.R 28 | import de.grobox.blitzmail.send.SendActivity 29 | import de.grobox.blitzmail.send.SendActivity.ACTION_RESEND 30 | import de.grobox.blitzmail.send.scheduleSending 31 | 32 | class NotificationHandlerActivity : Activity() { 33 | 34 | companion object { 35 | const val ACTION_DIALOG = "de.grobox.blitzmail.action.DIALOG" 36 | const val ACTION_FINISH = "de.grobox.blitzmail.action.FINISH" 37 | const val ACTION_SEND_LATER = "de.grobox.blitzmail.action.SEND_LATER" 38 | const val ACTION_TRY_AGAIN = "de.grobox.blitzmail.action.TRY_AGAIN" 39 | const val EXTRA_MAIL_ID = "de.grobox.blitzmail.extra.mailId" 40 | } 41 | 42 | private lateinit var mailNotificationManager: MailNotificationManager 43 | 44 | override fun onCreate(savedInstanceState: Bundle?) { 45 | super.onCreate(savedInstanceState) 46 | 47 | mailNotificationManager = getMailNotificationManager(applicationContext) 48 | 49 | if (intent != null) { 50 | onNewIntent(intent) 51 | } 52 | } 53 | 54 | override fun onNewIntent(intent: Intent) { 55 | // show dialog for server errors 56 | when (intent.action) { 57 | ACTION_DIALOG -> { 58 | val mailId = intent.getStringExtra(EXTRA_MAIL_ID) 59 | val builder = AlertDialog.Builder(this, R.style.DialogTheme) 60 | .setTitle(intent.getStringExtra("ContentTitle")) 61 | .setMessage(intent.getStringExtra("ContentText")) 62 | .setIcon(android.R.drawable.ic_dialog_alert) 63 | // Add the buttons 64 | .setNegativeButton(resources.getString(R.string.delete)) { _, _ -> deleteMail(mailId) } 65 | .setNeutralButton(resources.getString(R.string.send_later)) { _, _ -> sendLater() } 66 | .setPositiveButton(resources.getString(R.string.try_again)) { _, _ -> tryAgain() } 67 | 68 | // Create and show the AlertDialog 69 | val dialog = builder.create() 70 | dialog.setCanceledOnTouchOutside(false) 71 | dialog.show() 72 | } 73 | ACTION_SEND_LATER -> sendLater() 74 | ACTION_TRY_AGAIN -> tryAgain() 75 | ACTION_FINISH -> killNotificationAndFinish() 76 | else -> finish() 77 | } 78 | } 79 | 80 | private fun sendLater() { 81 | // User clicked Cancel button 82 | if (BuildConfig.PRO) { 83 | scheduleSending() 84 | killNotificationAndFinish() 85 | } else { 86 | val builder = AlertDialog.Builder(this, R.style.DialogTheme) 87 | 88 | builder.setTitle(getString(R.string.app_name)) 89 | builder.setMessage(getString(R.string.error_lite_version)) 90 | builder.setIcon(android.R.drawable.ic_dialog_info) 91 | 92 | // Add the buttons 93 | builder.setPositiveButton(android.R.string.ok) { lite_dialog, _ -> 94 | val uri = Uri.parse("https://play.google.com/store/apps/details?id=de.grobox.blitzmail.pro") 95 | val intent = Intent(Intent.ACTION_VIEW, uri) 96 | if (intent.resolveActivity(packageManager) != null) { 97 | startActivity(intent) 98 | } 99 | lite_dialog.dismiss() 100 | finish() 101 | } 102 | builder.setNegativeButton(android.R.string.cancel) { dialog, _ -> 103 | dialog.dismiss() 104 | finish() 105 | } 106 | 107 | // Create and show the AlertDialog 108 | val dialog = builder.create() 109 | dialog.setCanceledOnTouchOutside(false) 110 | dialog.show() 111 | } 112 | } 113 | 114 | private fun tryAgain() { 115 | // Prepare start of new activity 116 | val intent = Intent(this, SendActivity::class.java) 117 | intent.action = ACTION_RESEND 118 | 119 | killNotificationAndFinish() 120 | 121 | startActivity(intent) 122 | } 123 | 124 | private fun deleteMail(mailId: String) { 125 | MailStorage.deleteMail(applicationContext, mailId) 126 | finish() 127 | } 128 | 129 | private fun killNotificationAndFinish() { 130 | mailNotificationManager.cancelErrorNotification() 131 | finish() 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/preferences/MailPreferences.kt: -------------------------------------------------------------------------------- 1 | package de.grobox.blitzmail.preferences 2 | 3 | import android.content.Context 4 | import android.preference.PreferenceManager 5 | import android.util.Log 6 | import de.grobox.blitzmail.crypto.Crypto 7 | import de.grobox.blitzmail.R 8 | import java.net.InetAddress 9 | import java.net.UnknownHostException 10 | import java.util.* 11 | 12 | 13 | fun getProperties(c: Context): Properties { 14 | val pref = PreferenceManager.getDefaultSharedPreferences(c) 15 | val crypto = Crypto(c) 16 | 17 | val recipients = pref.getString("pref_recipient", null) 18 | val sender = pref.getString("pref_sender", null) 19 | 20 | val server = pref.getString("pref_smtp_server", null) 21 | val port = pref.getString("pref_smtp_port", null) 22 | val encryption = pref.getString("pref_smtp_encryption", null) 23 | val auth = pref.getBoolean("pref_smtp_auth", false) 24 | val user = pref.getString("pref_smtp_user", null) 25 | var password = pref.getString("pref_smtp_pass", null) 26 | 27 | if (recipients == null) throw RuntimeException(c.getString(R.string.error_option_not_set) + " " + c.getString(R.string.pref_recipient)) 28 | if (sender == null) throw RuntimeException(c.getString(R.string.error_option_not_set) + " " + c.getString(R.string.pref_sender)) 29 | if (server == null) throw RuntimeException(c.getString(R.string.error_option_not_set) + " " + c.getString(R.string.pref_smtp_server)) 30 | if (port == null) throw RuntimeException(c.getString(R.string.error_option_not_set) + " " + c.getString(R.string.pref_smtp_port)) 31 | if (auth) { 32 | if (user == null) throw RuntimeException(c.getString(R.string.error_option_not_set) + " " + c.getString(R.string.pref_smtp_user)) 33 | if (password == null) throw RuntimeException(c.getString(R.string.error_option_not_set) + " " + c.getString(R.string.pref_smtp_pass)) 34 | 35 | // Decrypt password 36 | password = crypto.decrypt(password) 37 | } 38 | 39 | val props = Properties() 40 | props.setProperty("mail.transport.protocol", "smtp") 41 | props.setProperty("mail.host", server) 42 | val appName = c.getString(R.string.app_name) 43 | val from = (pref.getString("pref_sender_name", appName) ?: appName) + " <" + sender + ">" 44 | props.setProperty("mail.user", from) 45 | props.setProperty("mail.from", from) 46 | props.setProperty("mail.smtp.auth", auth.toString()) 47 | props.setProperty("mail.smtp.port", port) 48 | props.setProperty("mail.smtp.recipients", recipients) 49 | props.setProperty("mail.smtp.quitwait", "false") 50 | 51 | if (auth) { 52 | // set username and password 53 | props.setProperty("mail.smtp.user", user) 54 | props.setProperty("mail.smtp.pass", password) 55 | } else { 56 | // set some hostname for proper HELO greeting 57 | props.setProperty("mail.smtp.localhost", "android.com") 58 | } 59 | 60 | // set encryption properties 61 | if (encryption == "ssl") { 62 | Log.i("SendActivity", "Using SSL Encryption...") 63 | props.setProperty("mail.smtp.ssl.enable", "true") 64 | props.setProperty("mail.smtp.ssl.checkserveridentity", "true") 65 | } else if (encryption == "tls") { 66 | Log.i("SendActivity", "Using STARTTLS Encryption...") 67 | props.setProperty("mail.smtp.starttls.enable", "true") 68 | props.setProperty("mail.smtp.ssl.checkserveridentity", "true") 69 | } 70 | 71 | // try to get proper hostname and set fake one if failed 72 | if (props.getProperty("mail.smtp.localhost", "") == "android.com") { 73 | var hostname = "" 74 | try { 75 | hostname = InetAddress.getLocalHost().hostName 76 | } catch (e: UnknownHostException) { 77 | // do nothing 78 | } 79 | 80 | if (hostname != "localhost") { 81 | props.setProperty("mail.smtp.localhost", hostname) 82 | } 83 | } 84 | 85 | return props 86 | } 87 | -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/preferences/PrefFragment.java: -------------------------------------------------------------------------------- 1 | /* BlitzMail 2 | * Copyright (C) 2013 Torsten Grote 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program 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 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package de.grobox.blitzmail.preferences; 19 | 20 | import android.content.Context; 21 | import android.content.DialogInterface; 22 | import android.content.Intent; 23 | import android.content.SharedPreferences; 24 | import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 25 | import android.net.Uri; 26 | import android.os.Bundle; 27 | import android.preference.CheckBoxPreference; 28 | import android.preference.Preference; 29 | import android.preference.PreferenceCategory; 30 | import android.preference.PreferenceFragment; 31 | 32 | import org.json.JSONObject; 33 | 34 | import androidx.appcompat.app.AlertDialog; 35 | import de.grobox.blitzmail.BuildConfig; 36 | import de.grobox.blitzmail.MailStorage; 37 | import de.grobox.blitzmail.R; 38 | 39 | import static de.grobox.blitzmail.send.SendLaterWorkerKt.sendQueuedMails; 40 | 41 | public class PrefFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener { 42 | 43 | @Override 44 | public void onCreate(Bundle savedInstanceState) { 45 | super.onCreate(savedInstanceState); 46 | addPreferencesFromResource(R.xml.preferences); 47 | 48 | addSendNowPref(getActivity()); 49 | 50 | setPrefState(); 51 | } 52 | 53 | @Override 54 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 55 | if (key.equals("pref_smtp_auth")) { 56 | setPrefState(); 57 | } 58 | } 59 | 60 | private void setPrefState() { 61 | CheckBoxPreference authPref = (CheckBoxPreference) findPreference("pref_smtp_auth"); 62 | if(authPref.isChecked()) { 63 | findPreference("pref_smtp_user").setEnabled(true); 64 | findPreference("pref_smtp_pass").setEnabled(true); 65 | } else { 66 | findPreference("pref_smtp_user").setEnabled(false); 67 | findPreference("pref_smtp_pass").setEnabled(false); 68 | } 69 | } 70 | 71 | @Override 72 | public void onResume() { 73 | super.onResume(); 74 | getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); 75 | 76 | // recreate send now preference 77 | PreferenceCategory cat = (PreferenceCategory) findPreference("pref_sending"); 78 | if(cat.findPreference("pref_send_now") != null) { 79 | cat.removePreference(findPreference("pref_send_now")); 80 | } 81 | addSendNowPref(getActivity()); 82 | } 83 | 84 | @Override 85 | public void onPause() { 86 | super.onPause(); 87 | getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); 88 | } 89 | 90 | private void addSendNowPref(final Context c) { 91 | JSONObject mails = MailStorage.getMails(getActivity()); 92 | 93 | if(mails != null && mails.length() > 0) { 94 | PreferenceCategory targetCategory = (PreferenceCategory) findPreference("pref_sending"); 95 | 96 | Preference pref = new Preference(getActivity()); 97 | pref.setKey("pref_send_now"); 98 | pref.setTitle(R.string.pref_send_now); 99 | pref.setSummary(String.format(getResources().getString(R.string.pref_send_now_summary), mails.length())); 100 | 101 | pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { 102 | public boolean onPreferenceClick(Preference preference) { 103 | if(BuildConfig.PRO) { 104 | sendQueuedMails(getContext()); 105 | ((PreferenceCategory) findPreference("pref_sending")).removePreference(findPreference("pref_send_now")); 106 | } else { 107 | AlertDialog.Builder builder = new AlertDialog.Builder(c, R.style.DialogTheme); 108 | 109 | builder.setTitle(c.getString(R.string.app_name)); 110 | builder.setMessage(c.getString(R.string.error_lite_version)); 111 | builder.setIcon(android.R.drawable.ic_dialog_info); 112 | 113 | // Add the buttons 114 | builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 115 | public void onClick(DialogInterface dialog, int id) { 116 | Uri uri = Uri.parse("https://play.google.com/store/apps/details?id=de.grobox.blitzmail.pro"); 117 | Intent intent = new Intent(Intent.ACTION_VIEW, uri); 118 | if(intent.resolveActivity(c.getPackageManager()) != null) { 119 | c.startActivity(intent); 120 | } 121 | dialog.dismiss(); 122 | } 123 | }); 124 | builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { 125 | public void onClick(DialogInterface dialog, int id) { 126 | dialog.dismiss(); 127 | } 128 | }); 129 | 130 | // Create and show the AlertDialog 131 | AlertDialog dialog = builder.create(); 132 | dialog.setCanceledOnTouchOutside(false); 133 | dialog.show(); 134 | } 135 | 136 | return true; 137 | } 138 | }); 139 | 140 | targetCategory.addPreference(pref); 141 | } 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/send/MailSender.java: -------------------------------------------------------------------------------- 1 | package de.grobox.blitzmail.send; 2 | 3 | import com.provider.JSSEProvider; 4 | 5 | import org.json.JSONArray; 6 | import org.json.JSONException; 7 | import org.json.JSONObject; 8 | 9 | import java.io.IOException; 10 | import java.security.Security; 11 | import java.util.Date; 12 | import java.util.Properties; 13 | 14 | import javax.mail.Authenticator; 15 | import javax.mail.Message; 16 | import javax.mail.MessagingException; 17 | import javax.mail.Multipart; 18 | import javax.mail.PasswordAuthentication; 19 | import javax.mail.Session; 20 | import javax.mail.Transport; 21 | import javax.mail.internet.InternetAddress; 22 | import javax.mail.internet.MimeBodyPart; 23 | import javax.mail.internet.MimeMessage; 24 | import javax.mail.internet.MimeMultipart; 25 | 26 | import static de.grobox.blitzmail.send.SenderServiceKt.MAIL_DATE; 27 | 28 | class MailSender extends Authenticator { 29 | 30 | private Properties props; 31 | private JSONObject mail; 32 | private Session session; 33 | 34 | static { 35 | Security.addProvider(new JSSEProvider()); 36 | } 37 | 38 | MailSender(Properties props, JSONObject mail) { 39 | this.props = props; 40 | this.mail = mail; 41 | 42 | // get a new mail session, don't use the default one to ensure fresh sessions 43 | session = Session.getInstance(props, this); 44 | } 45 | 46 | @Override 47 | protected PasswordAuthentication getPasswordAuthentication() { 48 | return new PasswordAuthentication(props.getProperty("mail.smtp.user", ""), props.getProperty("mail.smtp.pass", "")); 49 | } 50 | 51 | synchronized void sendMail() throws Exception { 52 | 53 | if(mail.has("body")) { 54 | MimeMessage message = getMessage(); 55 | message.setText(mail.optString("body")); 56 | message.setSubject(mail.optString("subject")); 57 | 58 | String cc = mail.optString("cc", null); 59 | if(cc != null) { 60 | if(cc.indexOf(',') > 0) { 61 | message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc)); 62 | } else { 63 | message.setRecipient(Message.RecipientType.CC, new InternetAddress(cc)); 64 | } 65 | } 66 | 67 | Transport.send(message); 68 | } 69 | else if(mail.has("attachments")) { 70 | JSONArray attachments = mail.getJSONArray("attachments"); 71 | 72 | Multipart mp = new MimeMultipart(); 73 | 74 | for(int i = 0; i < attachments.length(); i++) { 75 | JSONObject attachment = attachments.getJSONObject(i); 76 | 77 | MimeBodyPart mbp = getMimeBodyPart(attachment); 78 | 79 | if(mbp != null) { 80 | mp.addBodyPart(mbp); 81 | } 82 | } 83 | 84 | if(mp.getCount() == 0) { 85 | throw new RuntimeException("Could not get attachment for mail."); 86 | } 87 | 88 | // actually send message 89 | MimeMessage message = getMessage(); 90 | message.setContent(mp); 91 | message.setSubject(mail.optString("subject")); 92 | Transport.send(message); 93 | } 94 | } 95 | 96 | private MimeBodyPart getMimeBodyPart(JSONObject attachment) throws IOException, MessagingException { 97 | MimeBodyPart mbp = new MimeBodyPart(); 98 | 99 | try { 100 | mbp.attachFile(attachment.getString("path")); 101 | mbp.setFileName(attachment.getString("filename")); 102 | mbp.setHeader("Content-Type", attachment.getString("mimeType") + "; name=" + mbp.getFileName()); 103 | } catch(JSONException e) { 104 | e.printStackTrace(); 105 | } 106 | 107 | return mbp; 108 | } 109 | 110 | private MimeMessage getMessage() throws Exception { 111 | MimeMessage message = new MimeMessage(session); 112 | message.setFrom(); // uses mail.user property 113 | long date = mail.optLong(MAIL_DATE); 114 | if (date != 0) { 115 | message.setSentDate(new Date(date)); 116 | } else { 117 | message.setSentDate(new Date()); 118 | } 119 | 120 | String recipients = props.getProperty("mail.smtp.recipients", ""); 121 | 122 | if(recipients.indexOf(',') > 0) { 123 | message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients)); 124 | } else { 125 | message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipients)); 126 | } 127 | 128 | return message; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/send/SendActivity.java: -------------------------------------------------------------------------------- 1 | /* BlitzMail 2 | * Copyright (C) 2013 Torsten Grote 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program 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 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package de.grobox.blitzmail.send; 19 | 20 | import android.app.NotificationManager; 21 | import android.content.DialogInterface; 22 | import android.content.Intent; 23 | import android.database.Cursor; 24 | import android.net.Uri; 25 | import android.os.Bundle; 26 | import android.provider.OpenableColumns; 27 | import android.widget.Toast; 28 | 29 | import org.json.JSONArray; 30 | import org.json.JSONException; 31 | import org.json.JSONObject; 32 | 33 | import java.io.File; 34 | import java.io.FileDescriptor; 35 | import java.io.FileInputStream; 36 | import java.io.FileNotFoundException; 37 | import java.io.FileOutputStream; 38 | import java.io.IOException; 39 | import java.io.InputStream; 40 | import java.io.OutputStream; 41 | import java.util.ArrayList; 42 | import java.util.Date; 43 | 44 | import androidx.annotation.NonNull; 45 | import androidx.annotation.Nullable; 46 | import androidx.annotation.RequiresApi; 47 | import androidx.appcompat.app.AlertDialog; 48 | import androidx.appcompat.app.AppCompatActivity; 49 | import androidx.core.app.ActivityCompat; 50 | import androidx.core.content.ContextCompat; 51 | import de.grobox.blitzmail.R; 52 | 53 | import static android.Manifest.permission.READ_EXTERNAL_STORAGE; 54 | import static android.content.Intent.ACTION_SEND; 55 | import static android.content.Intent.ACTION_SEND_MULTIPLE; 56 | import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 57 | import static android.content.pm.PackageManager.PERMISSION_GRANTED; 58 | import static android.os.Build.VERSION.SDK_INT; 59 | import static android.widget.Toast.LENGTH_LONG; 60 | import static de.grobox.blitzmail.send.SenderServiceKt.MAIL; 61 | import static de.grobox.blitzmail.send.SenderServiceKt.MAIL_ATTACHMENTS; 62 | import static de.grobox.blitzmail.send.SenderServiceKt.MAIL_BODY; 63 | import static de.grobox.blitzmail.send.SenderServiceKt.MAIL_CC; 64 | import static de.grobox.blitzmail.send.SenderServiceKt.MAIL_ID; 65 | import static de.grobox.blitzmail.send.SenderServiceKt.MAIL_SUBJECT; 66 | import static de.grobox.blitzmail.send.SenderServiceKt.MAIL_DATE; 67 | 68 | public class SendActivity extends AppCompatActivity { 69 | // define variables to be used in AsyncMailTask 70 | protected NotificationManager mNotifyManager; 71 | private int mailId; 72 | private boolean error = false, requestingPermission = false; 73 | private ArrayList uris; 74 | 75 | public static final String ACTION_RESEND = "BlitzMailReSend"; 76 | private static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 42; 77 | 78 | @Override 79 | protected void onCreate (Bundle savedInstanceState) { 80 | super.onCreate(savedInstanceState); 81 | 82 | // setup notification channels 83 | mNotifyManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 84 | 85 | // generate mail id from current time 86 | mailId = (int) (System.currentTimeMillis() - 1000000) / 100; 87 | 88 | // get and handle Intent 89 | Intent intent = getIntent(); 90 | String action = intent.getAction(); 91 | String type = intent.getType(); 92 | 93 | intent.addFlags(FLAG_ACTIVITY_NEW_TASK); 94 | 95 | if(ACTION_SEND.equals(action) && type != null) { 96 | if("text/plain".equals(type)) { 97 | handleSendText(intent); 98 | } 99 | else { 100 | handleSendAttachment(intent); 101 | } 102 | } else if(ACTION_SEND_MULTIPLE.equals(action)) { 103 | handleSendMultipleAttachment(intent); 104 | } else if(ACTION_RESEND.equals(action)) { 105 | sendMail(null); 106 | } else { 107 | showError(getString(R.string.error_noaction)); 108 | } 109 | 110 | if(!error && !requestingPermission) { 111 | finish(); 112 | } 113 | } 114 | 115 | @Override 116 | public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { 117 | if(requestCode == MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE) { 118 | requestingPermission = false; 119 | if(grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) { 120 | sendAttachment(getMailWithAttachments(uris)); 121 | finish(); 122 | } else { 123 | showError(getString(R.string.error_permission_denied)); 124 | } 125 | } 126 | } 127 | 128 | void handleSendText(Intent intent) { 129 | String text = intent.getStringExtra(Intent.EXTRA_TEXT); 130 | 131 | if(text != null) { 132 | //String email = intent.getStringExtra(Intent.EXTRA_EMAIL); 133 | String subject = intent.getStringExtra(Intent.EXTRA_SUBJECT); 134 | String cc = intent.getStringExtra(Intent.EXTRA_CC); 135 | 136 | // Check for empty content 137 | if(subject == null || subject.isEmpty()) { 138 | // cut all characters from subject after the 128th 139 | subject = text.substring(0, (text.length() < 128) ? text.length() : 128); 140 | // remove line breaks from subject 141 | subject = subject.replace("\n", " ").replace("\r", " "); 142 | } 143 | 144 | // create JSON object with mail information 145 | JSONObject jMail = new JSONObject(); 146 | try { 147 | jMail.put(MAIL_ID, mailId); 148 | jMail.put(MAIL_BODY, text); 149 | jMail.put(MAIL_SUBJECT, subject); 150 | jMail.put(MAIL_CC, cc); 151 | jMail.put(MAIL_DATE, new Date().getTime()); 152 | } catch (JSONException e) { 153 | e.printStackTrace(); 154 | } 155 | 156 | // Start Mail Task 157 | sendMail(jMail); 158 | } else { 159 | showError(getString(R.string.error_no_body_no_subject)); 160 | } 161 | } 162 | 163 | private void handleSendAttachment(Intent intent) { 164 | Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM); 165 | 166 | ArrayList list = new ArrayList<>(1); 167 | list.add(uri); 168 | 169 | sendAttachment(getMailWithAttachments(list)); 170 | } 171 | 172 | private void handleSendMultipleAttachment(Intent intent) { 173 | ArrayList attachmentUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); 174 | 175 | sendAttachment(getMailWithAttachments(attachmentUris)); 176 | } 177 | 178 | private void sendAttachment(@Nullable JSONObject jMail) { 179 | if (jMail == null && requestingPermission) { 180 | return; 181 | } else if(jMail == null) { 182 | showError(getString(R.string.error_attachment)); 183 | return; 184 | } 185 | 186 | try { 187 | String num = String.valueOf(jMail.getJSONArray("attachments").length()); 188 | jMail.put("subject", num + " " + getString(R.string.files_shared) + " " + getString(R.string.app_name)); 189 | } catch(JSONException e) { 190 | e.printStackTrace(); 191 | } 192 | 193 | // Start Mail Task 194 | sendMail(jMail); 195 | } 196 | 197 | @Nullable 198 | private JSONObject getMailWithAttachments(ArrayList attachmentUris) { 199 | if(attachmentUris != null) { 200 | // check if permission is needed for an URI and request if so 201 | for(Uri uri : attachmentUris) { 202 | if("file".equals(uri.getScheme()) && SDK_INT >= 23) requestPermission(); 203 | if (requestingPermission) { 204 | uris = attachmentUris; 205 | return null; 206 | } 207 | } 208 | 209 | // create JSON object with mail information 210 | try { 211 | JSONObject jMail = new JSONObject(); 212 | jMail.put("id", mailId); 213 | JSONArray attachments = new JSONArray(); 214 | 215 | for(Uri uri : attachmentUris) { 216 | JSONObject attachment = new JSONObject(); 217 | 218 | // get file name 219 | String filename; 220 | Cursor cursor = getContentResolver().query(uri, null, null, null, null); 221 | if(cursor != null) { 222 | int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); 223 | cursor.moveToFirst(); 224 | filename = cursor.getString(nameIndex); 225 | cursor.close(); 226 | } 227 | else { 228 | filename = uri.getLastPathSegment(); 229 | } 230 | attachment.put("filename", filename); 231 | 232 | // copy file into a temporary file 233 | try { 234 | File file = File.createTempFile(filename, null); 235 | FileOutputStream fos = new FileOutputStream(file); 236 | 237 | FileDescriptor fd = getContentResolver().openFileDescriptor(uri, "r").getFileDescriptor(); 238 | FileInputStream fis = new FileInputStream(fd); 239 | 240 | copyLarge(fis, fos); 241 | 242 | attachment.put("path", file.getAbsolutePath()); 243 | } 244 | catch(FileNotFoundException e) { 245 | showError(getString(R.string.error_file_not_found)); 246 | return null; 247 | } 248 | catch(IOException e) { 249 | e.printStackTrace(); 250 | } 251 | 252 | // get mime type 253 | String mimeType = getContentResolver().getType(uri); 254 | if(mimeType == null) { 255 | // guess mime type 256 | if(filename.endsWith(".jpg") || filename.endsWith(".jpeg")) { 257 | mimeType = " image/jpeg"; 258 | } else { 259 | mimeType = "application/octet-stream"; 260 | } 261 | } 262 | attachment.put("mimeType", mimeType); 263 | 264 | attachments.put(attachment); 265 | } 266 | jMail.put(MAIL_ATTACHMENTS, attachments); 267 | 268 | return jMail; 269 | } catch (JSONException e) { 270 | e.printStackTrace(); 271 | } 272 | } 273 | return null; 274 | } 275 | 276 | private void sendMail(@Nullable JSONObject jMail) { 277 | Intent intent = new Intent(this, SenderService.class); 278 | intent.putExtra(MAIL, jMail == null ? null : jMail.toString()); 279 | ContextCompat.startForegroundService(this, intent); 280 | } 281 | 282 | @RequiresApi(api = 16) 283 | private void requestPermission() { 284 | if(ContextCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE) != PERMISSION_GRANTED) { 285 | // Should we show an explanation? 286 | if (ActivityCompat.shouldShowRequestPermissionRationale(this, READ_EXTERNAL_STORAGE)) { 287 | Toast.makeText(this, R.string.error_no_permission, LENGTH_LONG).show(); 288 | } else { 289 | requestingPermission = true; 290 | ActivityCompat.requestPermissions(this, new String[]{READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE); 291 | } 292 | } 293 | } 294 | 295 | private void showError(String text) { 296 | error = true; 297 | // close notification first 298 | mNotifyManager.cancel(mailId); 299 | 300 | AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.DialogTheme); 301 | 302 | builder.setTitle(getString(R.string.app_name) + " - " + getString(R.string.error)); 303 | builder.setMessage(text); 304 | builder.setIcon(android.R.drawable.ic_dialog_alert); 305 | 306 | // Add the buttons 307 | builder.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() { 308 | public void onClick(DialogInterface dialog, int id) { 309 | // User clicked Cancel button, close this Activity 310 | finish(); 311 | } 312 | }); 313 | // Create and show the AlertDialog 314 | AlertDialog dialog = builder.create(); 315 | dialog.setCanceledOnTouchOutside(false); 316 | dialog.show(); 317 | } 318 | 319 | private static void copyLarge(InputStream input, OutputStream output) throws IOException { 320 | byte[] buffer = new byte[4096]; 321 | int n; 322 | while (-1 != (n = input.read(buffer))) { 323 | output.write(buffer, 0, n); 324 | } 325 | } 326 | 327 | } 328 | -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/send/SendLaterWorker.kt: -------------------------------------------------------------------------------- 1 | package de.grobox.blitzmail.send 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import androidx.core.content.ContextCompat.startForegroundService 6 | import androidx.work.* 7 | import androidx.work.ListenableWorker.Result.success 8 | import de.grobox.blitzmail.send.SendActivity.ACTION_RESEND 9 | import java.util.concurrent.TimeUnit 10 | 11 | class SendLaterWorker(context: Context, params: WorkerParameters) : Worker(context, params) { 12 | 13 | override fun doWork(): Result { 14 | val intent = Intent(applicationContext, SenderService::class.java) 15 | startForegroundService(applicationContext, intent) 16 | return success() 17 | } 18 | 19 | } 20 | 21 | fun scheduleSending(delayInMinutes: Long = 5) { 22 | val workManager = WorkManager.getInstance() 23 | val constraints = Constraints.Builder() 24 | .setRequiredNetworkType(NetworkType.CONNECTED) 25 | .build() 26 | val worker = OneTimeWorkRequestBuilder() 27 | .setInitialDelay(delayInMinutes, TimeUnit.MINUTES) 28 | .setConstraints(constraints) 29 | .build() 30 | workManager.enqueue(worker) 31 | } 32 | 33 | fun sendQueuedMails(context: Context) { 34 | val intent = Intent(context, SendActivity::class.java) 35 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 36 | intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK) 37 | intent.action = ACTION_RESEND 38 | context.startActivity(intent) 39 | } 40 | -------------------------------------------------------------------------------- /src/de/grobox/blitzmail/send/SenderService.kt: -------------------------------------------------------------------------------- 1 | package de.grobox.blitzmail.send 2 | 3 | import android.app.IntentService 4 | import android.content.Intent 5 | import android.net.ConnectivityManager 6 | import android.os.Handler 7 | import android.widget.Toast 8 | import android.widget.Toast.LENGTH_LONG 9 | import de.grobox.blitzmail.BuildConfig 10 | import de.grobox.blitzmail.MailStorage 11 | import de.grobox.blitzmail.R 12 | import de.grobox.blitzmail.notification.MailNotificationManager 13 | import de.grobox.blitzmail.notification.NOTIFICATION_ID_SENDING 14 | import de.grobox.blitzmail.notification.getMailNotificationManager 15 | import de.grobox.blitzmail.preferences.getProperties 16 | import org.json.JSONObject 17 | 18 | const val MAIL = "mail" 19 | const val MAIL_ID = "id" 20 | const val MAIL_BODY = "body" 21 | const val MAIL_SUBJECT = "subject" 22 | const val MAIL_CC = "cc" 23 | const val MAIL_DATE = "date" 24 | const val MAIL_ATTACHMENTS = "attachments" 25 | 26 | class SenderService : IntentService("SenderService") { 27 | 28 | private lateinit var mailNotificationManager: MailNotificationManager 29 | private lateinit var connectivityManager: ConnectivityManager 30 | 31 | override fun onCreate() { 32 | super.onCreate() 33 | mailNotificationManager = getMailNotificationManager(applicationContext) 34 | connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager 35 | } 36 | 37 | override fun onHandleIntent(intent: Intent?) { 38 | if (intent == null) return 39 | 40 | mailNotificationManager.createNotificationChannel(); 41 | startForeground(NOTIFICATION_ID_SENDING, mailNotificationManager.getForegroundNotification()); 42 | 43 | intent.getStringExtra(MAIL)?.let { 44 | // save mail before sending all saved mails 45 | MailStorage.saveMail(this, JSONObject(it)) 46 | } 47 | 48 | // send all saved mails 49 | val mails = MailStorage.getMails(this) 50 | mails.keys().forEach { 51 | val mail = mails.getJSONObject(it); 52 | sendMail(mail) 53 | } 54 | } 55 | 56 | override fun onDestroy() { 57 | super.onDestroy() 58 | stopForeground(true) 59 | } 60 | 61 | private fun sendMail(mail: JSONObject) { 62 | val mailId = mail.getInt(MAIL_ID) 63 | val subject = mail.getString(MAIL_SUBJECT) 64 | try { 65 | MailSender(getProperties(applicationContext), mail).sendMail() 66 | 67 | mailNotificationManager.showSuccessNotification(mailId, subject) 68 | 69 | // Everything went fine, so delete mail from local storage 70 | MailStorage.deleteMail(applicationContext, mailId.toString()) 71 | } catch (e: Exception) { 72 | e.printStackTrace() 73 | 74 | val networkInfo = connectivityManager.activeNetworkInfo 75 | if (BuildConfig.PRO && (networkInfo == null || !networkInfo.isConnected)) { 76 | scheduleSending(0) 77 | Handler(mainLooper).post { 78 | Toast.makeText(applicationContext, getString(R.string.mail_queued), LENGTH_LONG).show() 79 | } 80 | } else { 81 | mailNotificationManager.showErrorNotification(e, mailId.toString()) 82 | } 83 | } 84 | } 85 | 86 | } 87 | --------------------------------------------------------------------------------