diff --git a/kalarm/Changelog b/kalarm/Changelog index edcd789b99..84c724a6dd 100644 --- a/kalarm/Changelog +++ b/kalarm/Changelog @@ -1,824 +1,824 @@ KAlarm Change Log -=== Version 2.4.2 --- 24 January 2010 === +=== Version 2.4.2 --- 30 January 2010 === - Fix non-ASCII text being corrupted in emails sent by KAlarm. - Show error message if selected email identity has no email address. === Version 2.4.1 (KDE 4.4.0 RC1) --- 8 December 2009 === - Fix date-only recurring alarms triggering repeatedly at high frequency. === Version 2.4.0 --- 24 November 2009 === - New audio alarm option, without displaying alarm window. - Add configuration setting for event duration for alarms copied to KOrganizer. - Provide 'any time' option in Defer Alarm dialogue, for date-only alarms. - Use KDE system settings to determine default working days in the week. - Improve organisation of main menu. - If dual screens, show alarm in other screen if any full screen window exists. - Fix recurring date-only alarm triggering repeatedly and eating up CPU, if the start-of-day time is after midnight and the alarm is due, but current UTC time of day is earlier than the start-of-day time of day in the alarm's time zone. - Update date-only alarm trigger times when user changes the start-of-day time. - Don't write start-of-day time into calendar, to avoid clashes if it is shared. - Don't waste processing time calculating next trigger time for archived alarms. - Disable 'New Alarm from Template' action when no alarm templates exist. - Interpret '~' (i.e. home directory) properly in entered file names. - Fix crash if calendar formats are updated at login, during session restoration. - Fix crash if editing alarm from alarm window Edit button, and window changes from reminder to normal, or window changes from at-login to final at-login trigger time, or window auto-closes. - Prevent infinite loop if NEXTRECUR time in alarm is before alarm start time. - Fix error saving the alarm after editing a repeat-at-login alarm. - Don't set reminder/late-cancel/show-in-KOrganizer when saving repeat-at-login alarms. - Improve error feedback in sound file selection. - Prevent sound file configuration dialogue closing after showing error message. === Version 2.3.0 --- 10 July 2009 === - Alarm edit: warn user if entered start time needs adjustment to fit recurrence. - Command alarm edit: show error message if no command/script has been entered. - Allow use of other command line options with --edit-new-* to initialise edit dialogue options. - Improve detection of conflicting command line options. === Version 2.2.4 --- 23 June 2009 === - Alarm edit: keep existing display file name if file select dialogue cancelled. - Guard against crashes if KAlarm quits while a modal dialogue is open. - Fix crash creating alarm from command line, if KAlarm not already running. - Fix --reminder-once command line option being treated same as --reminder. === Version 2.2.3 --- 14 June 2009 === - Fix crash when more than one alarm with audio is displayed simultaneously. === Version 2.2.2 --- 10 June 2009 === - Fix email alarms sending multiple mails, when sent by KMail. - Fix crash when closing remote calendars. === Version 2.2.1 --- 25 May 2009 === - Include new handbook translation: Ukrainian. === Version 2.2.0 --- 29 April 2009 === - Provide facility to export alarms to a new calendar file. - Provide option to spread alarm and error messages over screen. - Show command execution error indication for alarms in main window alarm list. - Add configuration setting for default deferral time in Defer Alarm dialogue. - Accept drag and drop of Todo entries to create a new alarm. === Version 2.1.8 (KDE 4.2.4) --- 25 May 2009 === - Fix crash on exit from birthday import dialogue. - Fix crash when an alarm is open for edit when its last occurrence triggers, and the edit is then saved. - Fix another possible crash when KAlarm quits. - Don't show time in alarm list for date-only alarms without time zone (e.g. those created by Import Birthdays). === Version 2.1.7 (KDE 4.2.3) --- 29 April 2009 === - Fix recurring alarms being missed when deferred to earlier than next due alarm, when next due alarm is earlier than the next recurrence. - Fix crash at startup if a non-recurring cancel-if-late alarm has been missed. - Fix speech mode not working when alarm messages are displayed. - Fix KAlarm hanging sometimes while trying to play an audio file. - Fix crash when KAlarm quits. - Fix memory leak with undo/redo. === Version 2.1.6 (KDE 4.2.2) --- 18 March 2009 === - Fix memory leaks. - Fix crash when KAlarm quits. === Version 2.1.5 (KDE 4.2.1) --- 7 February 2009 === - Disable inapplicable alarm types in alarm edit dialogue Load Template list. - Prevent multiple identical error messages being displayed for the same alarm. - Fix possible crash on alarm refresh, or removal or disabling of a resource. === Version 2.1.4 (KDE 4.2) --- 18 January 2009 === - Prevent corrupt alarms if deferral reinstates from archived alarm instead of from the displaying calendar. - Ignore events in calendar without usable alarms (which prevents them getting stuck in the alarm list, and fixes high CPU usage). - Show error message when New Template selected but no writable resource exists. - Fix crash when iCalendar item is dragged and dropped onto KAlarm. - Make New Alarm shortcuts work. - Fix alarms not being saved if created by drag-and-drop but not edited further. === Version 2.1.3 (KDE 4.2 RC1) --- 5 January 2009 === - Fix invalid alarm remaining in calendar when pre-alarm action failure message is acknowledged before the alarm is deferred. === Version 2.1.2 --- 27 December 2008 === - New KAlarm icon. - Distinguish disabled from enabled alarm colour when highlighted in alarm list. - Ensure alarm windows show on top of full-screen windows. - Fix crash if KAlarm is activated again while restoring from previous session. - Fix kalarmautostart crash on logout while kalarmautostart is still running. - Fix click on system tray icon not showing main window if 'Show in system tray' configuration setting deselected. === Version 2.1.1 (KDE 4.2 beta2) --- 8 December 2008 === - Allow global shortcuts for New Alarm actions. - Fix failure to update alarms in KOrganizer when Kontact is running but Kontact's calendar component is not loaded. - Fix toolbar configuration being lost after quitting KAlarm. === Version 2.1.0 (KDE 4.2 beta1) --- 13 November 2008 === - Add option to exclude holidays from recurring alarms. - Provide More/Less Options button in edit alarm dialogue. - Improve Configuration dialogue layout, split pages into tabs. - Show separate toolbar buttons for new display, command and email alarms. - Show 'Time Zone' button instead of time zone selection controls when using default time zone. - Set file display alarm font & colour in same way as for text display alarms. - Set default reminder time units according to how long until alarm is due. === Version 2.0.6 (KDE 4.1.3) --- 22 October 2008 === - Fix alarms not triggering correctly after laptop wakes from hibernation. - Fix inability to change or cancel alarm deferral times. - Prevent defer dialogue date being set outside the allowed range. - Set background colour for file display alarm text. - Don't wrap lines in file display alarm message windows. - Fix addition and deletion of alarms to KOrganizer. === Version 2.0.5 --- 27 September 2008 === - Fix very high CPU usage by KAlarm when there are alarms with sub-repetitions, or deferrals, with periods greater than 1 week. Fix requires kdepimlibs 4.1.3. === Version 2.0.4 (KDE 4.1.2)--- 24 September 2008 === - Add work-time-only parameter for D-Bus calls to create new alarms. === Version 2.0.3 --- 7 September 2008 === - Double click accepts selected template in pick list. - Make text in edit alarm dialogue change colour when foreground colour changed. - Replace colour combo boxes by buttons which display standard KDE colour picker. === Version 2.0.2 (KDE 4.1.1) --- 27 August 2008 === - Show alarm text entry fields in the current alarm message colours. - Show background colour selector for file display alarms. - Set KDE sound files directory as default for picking sound files. - Fix width of buttons containing only an icon. - Change Control Center references to System Settings. - Fix formatting of file display alarms for non-HTML text files. - Fix crash when birthday dialogue is opened more than once. - Prevent quitting when main window is closed but system tray icon is visible. === Version 2.0.2 --- 4 August 2008 === - Set KDE sound files directory as default for picking sound files. - Fix width of buttons containing only an icon. - Change Control Center references to System Settings. === Version 2.0.1 (KDE 4.1) --- 17 July 2008 === - Double click in template dialogue list activates template edit dialogue. - Fix KAlarm quitting on closing message window when no main window visible. - Fix KAlarm crashing when quitting. === Version 2.0.0 --- 7 July 2008 === - New facility to use multiple alarm calendar resources. - Add facility to select time zone for alarm times. - Handle summer/winter time changes correctly. - New option to trigger a recurring alarm only during working hours. - Add option for display alarm text to be generated by a command. - Provide "Don't show again for this alarm" option for command error messages. - Alarm edit dialogue layout improvements. - Make alarm edit and preferences dialogues scrollable if too high for screen. - Choose new alarm/template type from menu instead of in alarm edit dialogue. - Add option to show alarm windows in centre of screen, with buttons initially disabled to prevent accidental acknowledgement. - Remove alarm daemon (kalarmd) and do alarm monitoring in KAlarm itself. - Remove --handleEvent command line option. - Use custom properties instead of CATEGORIES in calendar events for KAlarm data. - Don't discard non-KAlarm custom event properties when editing alarms. - Use kconf_update to convert old config file settings. - Change numeric codes in config file to strings for long-term maintainability. - Rename Defaults section options in config file. - Fix detection of yearly February 29th recurrences on Feb 28th or Mar 1st. === Version 1.5.3 --- 16 June 2008 === - In New From Template menu, show list of template names in sorted order. - Fix recurrence count being lost when using alarm templates. - Prevent invalid negative values appearing in 'Time from now' edit field. - Fix time shown in alarm edit dialogue for recurring alarms. - Fix recurrence count shown in alarm edit dialogue once alarm has triggered. - Fix Find not working with a new search text after a failed search. - Display correct error message when a search fails. - Prevent user changing font/colour dialogue when editing read-only alarms. === Version 1.5.2 --- 13 February 2008 === - Prevent repetition duration error message when saving alarm which never recurs. === Version 1.5.1 (KDE 3.5.9) --- 13 February 2008 === - Fix inability to set up sub-repetitions for simple yearly recurrences. === Version 1.5.0 --- 23 January 2008 === - Replace simple repetitions with recurrence sub-repetitions, to save confusion. - Add option to enter reminder times in minutes, in addition to hours/minutes. - Replace alarm edit dialogue background colour selector with font/colour sample. - Store email unique IDs instead of names in email alarms to prevent problems if email IDs are renamed. - Fix error "Sender verify failed (in reply to RCPT TO command)" using sendmail on some systems, by adding envelope sender address to emails. - Fix OpenSolaris build error. === Version 1.4.21 --- 19 December 2007 === - Remember last used main window show/hide options instead of setting them in Preferences dialogue. - Make the Menu key work in the alarm list. - Fix crash when saving preferences, if 'xterm' is not installed in the system. - Prevent multiple identical error messages being displayed for the same alarm. === Version 1.4.20 --- 18 November 2007 === - Fix deferral of non-recurring alarms not working. - Fix loss of reminder details in archive when alarm has had a reminder deferred. - Fix inability to reactivate deleted alarms which still have repetitions to go. - Fix incorrect interpretation of --late-cancel weekly parameter on command line. === Version 1.4.19 --- 11 November 2007 === - Fix KAlarm hanging and freezing the system for a while, especially on startup. - Fix next occurrence time set after editing alarm, when it's a sub-repetition. - Prevent error messages while typing date value, until user finishes entering it. === Version 1.4.18 --- 2 November 2007 === - Fix failure to trigger some recurring date-only alarms (e.g. after suspend-resume). - Fix date-only alarms triggering every minute from midnight to start-of-day time. - Simplify recurrence text shown in alarm edit dialogue Alarm tab when possible. - Prevent error after browsing for command log file, due to file:// prefix. === Version 1.4.17 (KDE 3.5.8) --- 8 October 2007 === - Allow time-from-now values up to 999 hours to be entered. - Fix incorrect email headers resulting in failure to send some emails. === Version 1.4.16a --- 12 September 2007 === - Fix failure to retrieve font and colour settings for display alarms. === Version 1.4.16 --- 10 September 2007 === - Attempt to fix failure to retrieve font and colour settings for display alarms. - Disable reminder etc. controls for at-login recurrence in alarm edit dialogue. === Version 1.4.15 --- 7 September 2007 === - Fix deferrals of recurring alarms not triggering correctly. - Fix failure to archive details of repetitions within a recurrence. - Enable/disable "Show expired alarms" action when preferences change. === Version 1.4.14 --- 5 August 2007 === - Fix handling of exception dates in recurrences. - In sound file dialogue change Play button to a Stop button while playing a file. === Version 1.4.13 --- 18 May 2007 === - Fix time value in templates not being stored. - Expand time spin boxes to make room for all digits. - Make Preferences dialogue non-modal. === Version 1.4.12 (KDE 3.5.7) --- 11 May 2007 === - Display advance reminders for each occurrence of recurring alarms. - Fix Undo of deletion of active alarms. - Disable simple repetition controls if repetitions can't fit between recurrences. - Make the system tray tooltip take account of alarm repetitions. - Show repetition & special action status by button states in alarm edit dialogue. - Fix reminder alarms displaying very big numbers for how long until alarm is due. - Fix KMail omitting attachments from email alarms (if KMail is the email client). === Version 1.4.11 --- 16 April 2007 === - Prevent pre-alarm actions being executed multiple times when alarm is triggered. - Prevent alarm daemon triggering alarms multiple times. - Only execute pre-alarm actions once (not for reminders or deferrals). - Only execute post-alarm actions once when alarm is finally acknowledged (after any deferrals), and not after reminders. - Show file name as a tooltip on sound type combo box when "file" is selected. === Version 1.4.10 --- 3 March 2007 === - Add play button to sound file selection dialogue. - Prevent simple repetitions triggering again when KAlarm is restarted. - Fix recurring alarms being triggered on exception days. - Fix start-of-day time being ignored for date-only alarms. - Disable Defer button in new message window when deferral limit has been reached. - Fix failure to save "Execute in terminal window" option in Preferences dialogue. - Ensure up-to-date menus are displayed if user has a customised toolbar. === Version 1.4.9 (KDE 3.5.6) --- 3 January 2007 === - Minor changes. === Version 1.4.8 --- 28 December 2006 === - Fix Find always using first search text entered even after entering a new one. === Version 1.4.7 --- 14 December 2006 === - Fix crash saving Preferences dialogue (due to command alarm terminal setting). === Version 1.4.6 --- 30 November 2006 === - Fix crash if an alarm triggers while user is deleting it. - Fix "Start alarm monitoring at login" value shown in preferences dialogue. - Fix deselecting "Start alarm monitoring at login" when daemon not running. - Fix editing of 29th February alarm options for non-leap years. - Tidy up preferences dialogue Run mode options. - Tidy up alarm edit/preferences dialogue sound type options into a combo box. - Add context help for sound file fade options. === Version 1.4.5 (KDE 3.5.5) --- 29 September 2006 === - Improve alarm edit dialogue layout (Reminder controls moved to below Time box). === Version 1.4.4 --- 11 July 2006 === - Use an alarm's previous deferral time interval as default for its next deferral. === Version 1.4.3 (KDE 3.5.4) --- 11 July 2006 === - Add facility to import alarms from other calendar files. - Fix Defer dialog time interval maximum to match maximum date/time value. - Fix crash when a deferred expired recurring alarm is edited from message window. - Fix crash when a message is redisplayed after login. - Prevent inapplicable 'Unable to speak' error when alarm redisplayed after login. - Save main window column order changes to use on restart (except message column). === Version 1.3.10 (KDE 3.5.3) --- 22 May 2006 === - Add DCOP calls and command line options to display the edit alarm dialogue. - Add Select All and Deselect actions & shortcuts for import birthdays list. - Make system tray icon appear in non-KDE window managers. - Output error message if deleting copy of alarm from KOrganizer fails. - Fix corruption of alarms displayed at logout and then deferred after login. - Fix reminder time not being saved in alarm templates. - Fix erroneous date adjustment of start of recurrence when saving alarm. - Fix crash when --play command line option is used, if compiled without aRts. - Don't show disabled alarms in system tray tooltip alarm list. === Version 1.3.9 (KDE 3.5.2) --- 7 March 2006 === - Notify daemon by DCOP that alarm has been processed: to prevent alarm loss, and to prevent defunct kalarm processes when run mode is on-demand. - Add Select All and Deselect actions & shortcuts for alarm and template lists. === Version 1.3.8 --- 24 January 2006 === - Fix kalarmd hang when triggering late alarm and KAlarm run mode is on-demand. === Version 1.3.7 --- 22 January 2006 === - Fix column widths when main window is resized, if columns have been reordered. === Version 1.3.6 (KDE 3.5.1) --- 10 January 2006 === - Make autoclose of message windows work. - Fix New From Template not creating alarm if template contents are not changed. - Ensure that day and month names translations are independent of locale calendar. - Display alarm message windows within current screen in multi-head systems. - Reduce size of Preferences dialog to fit in 1024x768 screen. === Version 1.3.5 --- 14 December 2005 === - Fix email attachments being forgotten when saving alarms. - Fix toolbar configuration being lost after quitting KAlarm. === Version 1.3.4 (KDE 3.5) --- 30 October 2005 === - Fix incorrect recurrence frequency in Alarm Edit dialogue's Alarm tab. === Version 1.3.3 --- 22 September 2005 === - Add day-of-week selection to daily recurrence dialog. === Version 1.3.2 (KDE 3.5 beta 1) --- 10 September 2005 === - Add option to show alarms in KOrganizer's active calendar. - Add option for email text alarms to locate the email in KMail. - When email alarm triggers and KMail isn't running, start KMail and send mail automatically instead of opening KMail composer window. - Provide per-alarm option for yearly February 29th recurrences. - Wait longer (20 seconds) before reporting alarm daemon registration failed. - Minimise KMix window if KMix is started by KAlarm when displaying a message. - Fix Plastik style 'enabled' indication for time spinbox left-hand buttons. - Prevent message windows always being full screen after a big message is shown. - Prevent message windows being initially larger than the desktop. - Prevent message windows initially overlapping the KDE panel. - Prevent session restoration displaying main windows which should be hidden. - Fix alarms getting stuck if due during a daylight savings clock change. - Change --volume command line option short form to -V (-v is used by --version). - Fix reported shell errors when output from command alarm is discarded. - Use 'KAlarm' untranslated in calendar product ID, to cater for locale changes. === Version 1.3.1 --- 30 May 2005 === - Add Undo/Redo facility for alarm edit/creation/deletion/reactivation. - Add text search facility. - Add option to speak alarm messages (if speech synthesis is installed). - Add command line option --speak. - Add 'New alarm from template' menu option and toolbar button. - Add 'Time from now' option in alarm templates. - Add fade option for playing sound files. - Add option to log command alarm output to a file. - Add Edit button to alarm message window to allow the alarm to be edited. - Enable drag and drop of alarms to other applications. - Email drag-and-drop from KMail (KDE >= 3.5) now presets alarm edit dialog with full From/To/Cc/Subject headers and body text. === Version 1.2.8 (KDE 3.4.1) --- 9 May 2005 === - Fix failure to enable "Reminder for first recurrence only" checkbox. === Version 1.2.7 --- 20 April 2005 === - Use a sensible default for terminal window command in Preferences dialog. - Validate terminal window command entered in Preferences dialog. - Fix date range no longer being validated in Defer dialog. - Don't ignore Sound setting in Preferences dialog Edit tab. - Reset sound volume (if it was set) as soon as audio file playing is complete. - Don't start KMix when an alarm is displayed if no sound volume is specified. - Add command script and execute-in-terminal options to DCOP interface. === Version 1.2.6 (KDE 3.4) --- 22 February 2005 === - Pop up message windows far from cursor to avoid accidental acknowledgement. - Start KMix if not already running, for setting alarm sound level. - Fix alarms not triggering if IDs are duplicated in different calendar files. - Improve validation when reading configuration file values. === Version 1.2.5 (KDE 3.4 beta2) --- 21 January 2005 === - Prevent multiple "Failed to start Alarm Daemon" error messages at startup. - Fix missing left border for time spinboxes in Plastik style. === Version 1.2.4 (KDE 3.4 beta1) --- 9 January 2005 === - Provide option to enter a script for a command alarm, instead of a command line. - Add option to run command alarms in terminal windows. - Accept drag and drop of KAddressBook entries to alarm edit dialog email fields. - Drag and drop now inserts text where appropriate, rather than replacing it. - Display correct controls after loading a template in alarm edit dialog. === Version 1.2.3 --- 7 December 2004 === - Put alarm type icons in a separate, sortable, column in alarm list. - Align times in alarm list. - Fix crash when the last recurrence of an alarm is reached. - Fix random limit on expired alarm discard time if stepping with spinbox buttons. - Fix dialog layouts for right-to-left languages. - Fix time spin box layout for right-to-left languages. === Version 1.2.2 --- 27 November 2004 === - Make alarm daemon (kalarmd) exclusive to KAlarm. - Move control options for alarm daemon into KAlarm preferences dialog. - Allow user to specify the late-cancellation period for an alarm. - Add option to automatically close window after late-cancellation period. - Add facility to enable and disable individual alarms. - Add simple repetition facility, including repetition within a recurrence. - Add option to pick a KMail identity to use as sender of email alarms. - Add option to copy emails sent via sendmail, to KMail sent-mail folder. - Show scheduled times, not reminder times, in alarm list and system tray tooltip. - Make time edit controls use 12-hour clock when that is the user's default. - Also fill in alarm edit dialog email fields when email is dropped onto KAlarm. - New revised DCOP request interface (old interface still kept for compatibility). - Make detection of email message display alarms independent of language. - Use KMix whenever possible to set hardware sound volume. - Limit range of entered date/time to valid values in deferral dialogue. - Prevent kalarm failing to register with kalarmd except when really necessary. - Fix time-to-alarm column in main window not always updating every minute. === Version 1.1.7 (KDE 3.3.2) --- 27 November 2004 === - Fix KAlarm button on message windows to make it always display main window. - Show scheduled times, not reminder times, in alarm list and system tray tooltip. - Fix time-to-alarm column in main window not always updating every minute. === Version 1.1.6 (KDE 3.3.1) --- 30 September 2004 === - Prevent crash, and output error message, if menu creation fails. - Unsuppress Quit warning message box if default answer is Cancel quit. - Prevent blind copy to self of email alarms via KMail when bcc is deselected. === Version 1.1.5 --- 1 September 2004 === - Show erroneous control in alarm edit dialog when an error message is displayed. - Make alarm edit dialog always appear on current desktop. - Make weekly/monthly/yearly recurrences scheduled from command line correspond correctly to the start date. - Fix start date for monthly/yearly recurrences scheduled from the command line. - Fix DCOP triggerEvent() call to not reschedule alarm if it isn't due yet. === Version 1.1.4 --- 21 August 2004 === - Fix errors when altering or cancelling deferrals of expired recurrences. === Version 1.1.3 (KDE 3.3) --- 28 July 2004 === - Fix dialog sizing the first time KAlarm is run. === Version 1.1.2 (KDE 3.3 beta2) --- 11 July 2004 === - Fix hangup in interactions with alarm daemon introduced in version 1.1.1. - Only tick Alarms Enabled menu items once alarms have actually been enabled. - Fix build for "./configure --without-arts". === Version 1.1.1 (KDE 3.3 beta1) --- 20 June 2004 === - Output error message and disable alarms if can't register with alarm daemon. - Exit if error in alarm calendar name configuration. - Fix bug where sound file is selected even when Cancel is pressed. === Version 1.1.0 --- 1 June 2004 === - Add facility to define alarm templates. - Add facility to specify pre- and post-alarm shell command actions. - Add option to play sound file repeatedly until alarm window is closed. - Add volume control for playing sound file. - Add 'stop sound' button to alarm message window when sound file is played. - Rename command line option --sound to --play, add option --play-repeat. - Add command line option --volume. - Add 'Configure Shortcuts' and 'Configure Toolbars' menu options in main window. - After creating/editing alarm, prompt to re-enable alarms if currently disabled. - Middle mouse button over system tray icon displays new alarm dialog. - Add option to display a reminder once only before the first alarm recurrence. - Display time-to-alarm in reminder message window. - For message texts which are truncated in main window, show full text in tooltip. - Allow time of day to be entered in format HHMM in time spin boxes. - Allow hour to be omitted when colon format time is entered in time spin boxes. - Add "Don't ask again" option to alarm deletion confirmation prompt. - Prevent expired alarm calendar purges clashing with other alarm actions. - Fix initial recurrence date/time for weekly/monthly/yearly recurrences. - Fix yearly recurrences of the last day in the month. - Disable yearly recurrence's month checkboxes depending on selected day of month. - Update which time columns are displayed in alarm list when Preferences change. - Don't store audio/reminder details in email/command alarms. - Don't store email details in message/file/command alarms. - Don't close message windows when quit is selected. - Fix "Warn before quitting" configuration option. - Don't redisplay error message windows on session restoration. - Remove obsolete --displayEvent command line option (replaced by --triggerEvent). - Remove obsolete pre-version 0.7 DCOP calls. === Version 1.0.7 --- 2 May 2004 === - Fix scheduleCommand() and scheduleEmail() DCOP handling. - Make KAlarm build for "./configure --without-arts". - Fix email body text not being saved in email alarms. - Fix loss of --exec command line arguments. - Remove wasted vertical space from message windows. === Version 1.0.6 (KDE 3.2.2) --- 26 March 2004 === - Make the Quit menu item in main window quit the program. - Update time entry field after editing as soon as mouse cursor leaves it. - Cancel deferral if reminder is set before it, to prevent it becoming stuck. - Prevent undeleted recurring alarms being triggered immediately. - Don't allow alarms to be undeleted if they are completely expired. === Version 1.0.5 (KDE 3.2.1) --- 24 February 2004 === - Fix whatsThis text on bottom row of alarm list. === Version 1.0.4 --- 22 February 2004 === - Fix freeze at login when multiple alarms trigger. - Show all audio file types in sound file chooser dialogue. === Version 1.0.3 --- 15 February 2004 === - Prevent email alarms from being sent if no 'From' address is configured. - Omit 'Bcc' when sending email alarms if no 'Bcc' address is configured. - Fix freeze when starting the alarm daemon. - Fix memory leaks displaying dialogs. - Fix scheduleCommand() and scheduleEmail() DCOP handling. - Fix errors saving expired alarm calendar. === Version 1.0.2 (KDE 3.2) --- 29 January 2004 === - Prevent editing alarm and saving without changes from deleting the alarm. === Version 1.0.1 --- 4 January 2004 === - Fix failure to see alarms if KAlarm is reactivated while restoring session. === Version 1.0.0 --- 7 December 2003 === - Allow entered start date for timed recurrence events to be earlier than now. - Prevent attempted entry of recurrence end date earlier than start date or today. - Fix error displaying time of expired repeat-at-login alarms. - Fix memory leak when sending emails with attachments. - Fix error trying to send emails with very small attachments. - Eliminate duplicate reload-calendar calls to alarm daemon. === Version 0.9.6 (KDE 3.2 beta1) --- 7 November 2003 === - Add option to choose foreground colour for alarm messages. - Create new alarm by dragging KMail email onto main window or system tray icon. - Set initial recurrence defaults to correspond to alarm start date. - Add option for how February 29th recurrences are handled in non-leap years. - Monthly/yearly recurrence edit: adhere to user preference for start day of week. - Eliminate multiple confirmation prompts when deleting multiple alarms. - Eliminate duplicate alarms in system tray tooltip. - Fix crash after reporting error opening calendar file. - Fix wrong status in system tray icon if KAlarm starts up with alarms disabled. - Fix wrong number of days in Time-to-alarm column in main window. - Fix omission of deferred alarms from system tray tooltip. === Version 0.9.5 --- 3 September 2003 === - Add option for non-modal alarm message windows. - Add option to display a notification when an email alarm queues an email. - Emails via KMail are sent without opening composer window, if KMail is running. - Provide separate configuration for 'From' and 'Bcc' addresses for email alarms. - Add exceptions to recurrence specification. - Add multiple month selection to yearly recurrence. - Add day of month selection in yearly recurrence. - Add last day of month option in monthly and yearly recurrences. - Add 2nd - 5th last week of month options in monthly and yearly recurrences. - Add filename completion to file and command alarm edit fields. - Display alarms-disabled indication in system tray tooltip. - Enable file alarms to display image files. - Fix file alarms not dislaying some text files, and improve HTML file display. - Fix loss of changes to attachment list after editing email alarms. - Fix wrong recurrence end date being displayed when editing an existing alarm. === Version 0.9.4 --- 3 July 2003 === - Add time-to-alarm display option to main alarm list. - Add option to list next 24 hours' alarms in system tray tooltip. - Create new alarm by dragging text or URL onto main window or system tray icon. - Display reasons for failure to send an email. - Allow editing of the list of message colours. - Edit new alarm by context menu or double click on white space in alarm list. - Add show expired alarms option to preferences dialog. - Display HTML files correctly in file display alarms. === Version 0.9.3 --- 4 March 2003 === - Add preferences option to set default sound file for the Edit Alarm dialog. - Fix display of "Invalid date" message before Edit Alarm dialog displays. === Version 0.9.2 --- 28 February 2003 === - Option to set font for individual alarm messages. - Allow multiple alarm selection in the main window. - KAlarm icon in alarm message window selects the alarm in the main window. - In Edit Alarm dialog, move all recurrence edit controls into Recurrence tab. - Add quit warning message option to preferences dialog. - Add "New Alarm" option to system tray context menu. - Disallow command alarms when KDE is running in kiosk mode. - Revised storage of beep, font, colour and program arguments in calendar file. - Always save alarms in iCalendar format (but vCalendar may still be read). - Add reminder, recurrence and font parameters to DCOP calls. - Fix failure to enable alarms when running in on-demand mode. === Version 0.9.1 --- 16 January 2003 === - Add option to set advance reminders for display alarms. - In run-in-system-tray mode, warn that alarms will be disabled before quitting. - Fix monthly and yearly recurrences on nth Monday etc. of the month. - Fix yearly recurrences on February 29th. - Fix recurrence start times stored in expired calendar file. - Fix extra empty events being stored in expired calendar file. === Version 0.9.0 --- 3 January 2003 === - Add facility to import birthdays from KAddressBook - Add option to send an email instead of displaying an alarm message. - Add option to store and view expired alarms. - Add copy, view and undelete actions (as applicable) for the selected alarm. - In alarm message window, message text can be copied to clipboard using mouse. - Allow message text to be scrolled in alarm message window if too big to fit. - Shift key with left mouse button steps time edit arrows by 5 minutes/6 hours. - Report failure to run command alarm (bash, ksh shells only). - Retain repeat-at-login status on alarm deferral. - Restore alarm messages which were displayed before KAlarm was killed or crashed. - Store alarm data in the calendar file in a more standard way. - Alarm message defer dialog: update recurrence deferral time limit in real time. - Weekly recurrence edit: adhere to user preference for start day of week. - Use standard action icons. === Version 0.8.5 (KDE 3.1.1) --- 21 February 2003 === - Fix monthly and yearly recurrences on nth Monday etc. of the month. - Fix yearly recurrences on February 29th. - Fix failure to enable alarms when running in on-demand mode. === Version 0.8.4 (KDE 3.1) --- 8 January 2003 === - Make KAlarm icon in message window bring main window to current desktop. - Fix detection of KDE desktop. - Fix entry of yearly recurrences on a specified date in the year. === Version 0.8.3 --- 9 November 2002 === - Fix no system tray icon being displayed. - Fix multiple system tray icons being displayed. - Fix alarms being missed after changing "Disable alarms when not running" status. === Version 0.8.2 --- 2 November 2002 === - Fix audio files not playing. === Version 0.8.1 --- 1 November 2002 === - Adhere to KDE single/double click setting when clicking on alarm list. - Fix possible loss of alarms if KAlarm has previously used another calendar file. - Fix coordination between "At time" and "After time" values when they change. - Always remove alarm deferral even when next recurrence triggers instead. - When alarm triggers, replace any existing repeat-at-login alarm message window. - Fix deselection of Sound not working after selecting a sound file. - Fix display of hour spin buttons in time edit spin boxes. - Prevent time edit spin box buttons from selecting the text. - Clean up previous alarm list highlight properly when a new alarm is selected. - Set sensible initial focus when edit alarm dialog pages are displayed. - Fix Quit duplicate entry in system tray context menu. === Version 0.8 (KDE 3.1 beta2) --- 16 September 2002 === - Move recurrence edit to separate tab in alarm dialog (now fits 800x600 display). - Add accelerator keys in dialogs. - Provide date picker for entering dates. === Version 0.7.5 --- 1 September 2002 === - Add preferences options to choose default settings for the Edit Alarm dialog. - Fix right-to-left character sets not being displayed in message edit control. - Make "Help -> Report Bug" use the KDE bug system (bug #43250). - Fix session restoration not occurring. === Version 0.7.4 (KDE 3.1 beta1) --- 5 August 2002 === - Add option to prompt for confirmation on alarm deletion. - Add option to prompt for confirmation on alarm acknowedgement. - Display KAlarm handbook Preferences section when Help clicked in config dialog. - Correctly adjust wrong summer times stored by version 0.5.7 (KDE 3.0.0). === Version 0.7.3 --- 24 July 2002 === - Fix loss of alarm times after saving pre-version 0.7 calendar file. - Fix main alarm list display of hours or hours/minutes repeat interval. - Display KAlarm handbook when Help clicked in configuration dialog. === Version 0.7.2 --- 2 July 2002 === - Fix reading wrong alarm times from pre-version 0.7 calendar file. - Partially fix loss of alarm times after saving pre-version 0.7 calendar file. === Version 0.7.1 --- 29 June 2002 === - Prevent duplicate message windows from being displayed. - Make Close button on message window not the default button to reduce chance of accidental acknowledgement. - Fix non-ASCII message texts being saved as question marks. - Fix memory leak with recurrences. === Version 0.7.0 --- 15 June 2002 === - Add option to play audio file when message is displayed. - Add daily, weekly, monthly, annual recurrences. - Allow deferring only up to next scheduled repetition time. - Don't defer repetitions when an alarm is deferred. - Make regular repetition and repeat-at-login mutually exclusive. - Double click on alarm in main window opens alarm edit dialog. - Change Reset Daemon menu option to Refresh Alarms. - Save and restore window sizes. === Version 0.6.4 --- 8 May 2002 === - Make click on system tray icon always bring KAlarm to top on current desktop. - Fix alarms not being triggered (depending on time zone). === Version 0.6.0 --- 8 March 2002 === - Add option to execute a command instead of displaying an alarm message. - Add Try button to alarm message edit dialog. - Add icons in the alarm list to indicate each alarm's type. - Display error message if a file to be displayed is not a text file. - Reduce chance of lost late-cancel alarms when daemon check interval is reduced. - Rename command line option --displayEvent to --triggerEvent. - Rename DCOP function displayMessage() to triggerEvent(). - Rename DCOP function cancelMessage() to cancelEvent(). === Version 0.5.8 (KDE 3.0.5A) --- 23 November 2002 === - Fix detection of KDE desktop. === Version 0.5.8 (KDE 3.0.5) --- 4 October 2002 === - Fix possible loss of alarms if KAlarm has previously used another calendar file. === Version 0.5.8 (KDE 3.0.4) --- 18 August 2002 === - Make "Help -> Report Bug" use the KDE bug system (bug #43250). - Fix right-to-left character sets not being displayed in message edit control. === Version 0.5.8 (KDE 3.0.3) --- 5 August 2002 === - Adjust wrong summer times stored by version 0.5.7 (KDE 3.0.0). - Display KAlarm handbook when Help clicked in configuration dialog. - Make Close button on message window not the default button to reduce chance of accidental acknowledgement. - Fix session restoration often not occurring at login. === Version 0.5.7 (KDE 3.0.1) --- 9 May 2002 === - Use local time for alarm times instead of using a time zone. - Make click on system tray icon always bring KAlarm to top on current desktop. === Version 0.5.7 (KDE 3.0) --- 17 March 2002 === - Show system tray icon on deferring command line-initiated message (run-in- system-tray mode). - Associate main window with system tray icon when displayed from message window. - Don't start KAlarm at login, until it has been run for the first time. - Add startup notification to kalarm.desktop. - Prevent open main window from cancelling KDE session shutdown. - Fix failure to display messages after daemon is restarted (run-on-demand mode). - Fix possible failure to display command line-initiated message. - Fix crash in some circumstances on changing run mode to run-on-demand. - Fix crash on clicking KAlarm icon in command line-initiated message window. - Fix crash on deferring alarm in command line-initiated message window. - Fix duplication of repeat-at-login alarms at login. - Fix error displaying text file messages. === Version 0.5.4 --- 7 February 2002 === - Fix extra window being displayed in session restoration. === Version 0.5.2 --- 31 January 2002 === - Fix session restore crash if in 'run continuously in system tray' mode. === Version 0.5.1 --- 30 January 2002 === - Change configuration defaults. === Version 0.5 --- 29 January 2002 === - Incorporate system tray icon into KAlarm, add --tray option. - Add 'run continuously in system tray' operating mode. - Don't use alarm daemon GUI application. - Add enable/disable alarms option to main window menu. - Add show/hide system tray icon option to main window menu. - Add toolbar. - Rename alarm dialog Set Alarm button to OK. - Rename message window OK button to Close. - Remove keyboard accelerator for Reset Daemon. - Fix magnified system tray icon. - Include README, etc. files in installation. === Version 0.4 --- 22 December 2001 === - Modify to use split alarm daemon/alarm daemon GUI. - Prevent a command line error exiting all open KAlarm windows. - Ensure the program exits after starting with --stop or --reset options. === Version 0.3.5 --- 5 December 2001 === - Add option to repeat alarms at login. - Add context help button to main window and message window. - Fix occasional crash on displaying non-repeating alarms. - Fix possible failure to display alarms at login. - Fix blank title bar when main window restored at login. - Fix alarms not deleted from main window when displayed at login. - Fix handling of zero-length calendar file. - Improve error messages. - Make documentation files installation dependent on KDE version. === Version 0.3.1 --- 20 November 2001 === - Fix build fault when using ./configure --enable-final === Version 0.3 --- 4 November 2001 === - Add option to display a file's contents instead of specifying a message. - Add dialog option to set an alarm's time as an interval from the current time. - Add defer option to alarm message window. - Provide button in alarm message window to activate KAlarm. - Make dialogs modal only for their parent window. === Version 0.2 --- 20 October 2001 === - Implement repeating alarms. - Add extra pair of arrow buttons to time spinbox to change the hour. - Fix sorting by colour column. - Better What's This? texts for the main window. - Remove -r, -s short options (use --reset, --stop instead). === Version 0.1.1 --- 1 September 2001 === - Fix documentation not being created by build. === Version 0.1 --- 31 August 2001 === - Initial release. diff --git a/kalarm/kamail.cpp b/kalarm/kamail.cpp index e61c675bab..83d00c8d19 100644 --- a/kalarm/kamail.cpp +++ b/kalarm/kamail.cpp @@ -1,955 +1,964 @@ /* * kamail.cpp - email functions * Program: kalarm * Copyright © 2002-2010 by David Jarvie * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kalarm.h" //krazy:exclude=includes (kalarm.h must be first) #include "kamail.h" #include "functions.h" #include "identities.h" #include "kalarmapp.h" #include "mainwindow.h" #include "preferences.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef KMAIL_SUPPORTED #include "kmailinterface.h" static const char* KMAIL_DBUS_SERVICE = "org.kde.kmail"; static const char* KMAIL_DBUS_PATH = "/KMail"; #endif namespace HeaderParsing { bool parseAddress( const char* & scursor, const char * const send, KMime::Types::Address & result, bool isCRLF=false ); } static void initHeaders(KMime::Message&, KAMail::JobData&); static KMime::Types::Mailbox::List parseAddresses(const QString& text, QString& invalidItem); static QByteArray autoDetectCharset(const QString& text); static const QTextCodec* codecForName(const QByteArray& str); QString KAMail::i18n_NeedFromEmailAddress() { return i18nc("@info/plain", "A 'From' email address must be configured in order to execute email alarms."); } QString KAMail::i18n_sent_mail() { return i18nc("@info/plain KMail folder name: this should be translated the same as in kmail", "sent-mail"); } KAMail* KAMail::mInstance = 0; // used only to enable signals/slots to work QQueue KAMail::mJobs; QQueue KAMail::mJobData; KAMail* KAMail::instance() { if (!mInstance) mInstance = new KAMail(); return mInstance; } /****************************************************************************** * Send the email message specified in an event. * Reply = 1 if the message was sent - 'errmsgs' may contain copy error messages. * = 0 if the message is queued for sending. * = -1 if the message was not sent - 'errmsgs' contains the error messages. */ int KAMail::send(JobData& jobdata, QStringList& errmsgs) { QString err; KPIMIdentities::Identity identity; if (!jobdata.event.emailFromId()) jobdata.from = Preferences::emailAddress(); else { identity = Identities::identityManager()->identityForUoid(jobdata.event.emailFromId()); if (identity.isNull()) { kError() << "Identity" << jobdata.event.emailFromId() << "not found"; errmsgs = errors(i18nc("@info", "Invalid 'From' email address.Email identity %1 not found", jobdata.event.emailFromId())); return -1; } if (identity.emailAddr().isEmpty()) { kError() << "Identity" << identity.identityName() << "uoid" << identity.uoid() << ": no email address"; errmsgs = errors(i18nc("@info", "Invalid 'From' email address.Email identity %1 has no email address", identity.identityName())); return -1; } jobdata.from = identity.fullEmailAddr(); } if (jobdata.from.isEmpty()) { switch (Preferences::emailFrom()) { #ifdef KMAIL_SUPPORTED case Preferences::MAIL_FROM_KMAIL: errmsgs = errors(i18nc("@info", "No 'From' email address is configured (no default email identity found)" "Please set it in KMail or in the KAlarm Configuration dialog.")); break; #endif case Preferences::MAIL_FROM_SYS_SETTINGS: errmsgs = errors(i18nc("@info", "No 'From' email address is configured." "Please set it in the KDE System Settings or in the KAlarm Configuration dialog.")); break; case Preferences::MAIL_FROM_ADDR: default: errmsgs = errors(i18nc("@info", "No 'From' email address is configured." "Please set it in the KAlarm Configuration dialog.")); break; } return -1; } jobdata.bcc = (jobdata.event.emailBcc() ? Preferences::emailBccAddress() : QString()); kDebug() << "To:" << jobdata.event.emailAddresses(",") << endl << "Subject:" << jobdata.event.emailSubject(); MailTransport::TransportManager* manager = MailTransport::TransportManager::self(); MailTransport::Transport* transport = 0; if (Preferences::emailClient() == Preferences::sendmail) { kDebug() << "Sending via sendmail"; - transport = manager->transportByName(QLatin1String("sendmail"), false); + const QList transports = manager->transports(); + for (int i = 0, count = transports.count(); i < count; ++i) + { + if (transports[i]->type() == MailTransport::Transport::EnumType::Sendmail) + { + // Use the first sendmail transport found + transport = transports[i]; + break; + } + } if (!transport) { QString command = KStandardDirs::findExe(QLatin1String("sendmail"), QLatin1String("/sbin:/usr/sbin:/usr/lib")); transport = manager->createTransport(); transport->setName(QLatin1String("sendmail")); transport->setType(MailTransport::Transport::EnumType::Sendmail); transport->setHost(command); transport->setRequiresAuthentication(false); transport->setStorePassword(false); manager->addTransport(transport); transport->writeConfig(); kDebug() << "Creating sendmail transport, id=" << transport->id(); } } else { kDebug() << "Sending via KDE"; transport = manager->transportByName(identity.transport(), true); if (!transport) { kError() << "No mail transport found for identity" << identity.identityName() << "uoid" << identity.uoid(); errmsgs = errors(i18nc("@info", "No mail transport configured for email identity %1", identity.identityName())); return -1; } } - int transportId = transport->id(); - MailTransport::TransportJob* mailjob = manager->createTransportJob(transportId); + kDebug() << "Using transport" << transport->name() << ", id=" << transport->id(); + MailTransport::TransportJob* mailjob = manager->createTransportJob(transport->id()); if (!mailjob) { kError() << "Failed to create mail transport job for identity" << identity.identityName() << "uoid" << identity.uoid(); errmsgs = errors(i18nc("@info", "Unable to create mail transport job")); return -1; } KMime::Message message; initHeaders(message, jobdata); err = appendBodyAttachments(message, jobdata); if (!err.isNull()) { kError() << "Error compiling message:" << err; errmsgs = errors(err); return -1; } mailjob->setSender(KPIMUtils::extractEmailAddress(jobdata.from)); mailjob->setTo(jobdata.event.emailPureAddresses()); if (!jobdata.bcc.isEmpty()) mailjob->setBcc(QStringList(KPIMUtils::extractEmailAddress(jobdata.bcc))); mailjob->setData(message.encodedContent()); mJobs.enqueue(mailjob); mJobData.enqueue(jobdata); if (mJobs.count() == 1) { // There are no jobs already active or queued, so send now connect(mailjob, SIGNAL(result(KJob*)), instance(), SLOT(slotEmailSent(KJob*))); mailjob->start(); } return 0; } /****************************************************************************** * Called when sending an email is complete. */ void KAMail::slotEmailSent(KJob* job) { bool fail = false; bool copyerr = false; QStringList errmsgs; if (job->error()) { kError() << "Failed:" << job->errorString(); errmsgs = errors(job->errorString(), SEND_ERROR); fail = true; } JobData jobdata; if (mJobs.isEmpty() || mJobData.isEmpty() || job != mJobs.head()) { // The queue has been corrupted, so we can't locate the job's data kError() << "Wrong job at head of queue: wiping queue"; mJobs.clear(); mJobData.clear(); if (!errmsgs.isEmpty()) theApp()->emailSent(jobdata, errmsgs); errmsgs.clear(); errmsgs += i18nc("@info", "Emails may not have been sent"); errmsgs += i18nc("@info", "Program error"); theApp()->emailSent(jobdata, errmsgs); return; } mJobs.dequeue(); jobdata = mJobData.dequeue(); #ifdef KMAIL_SUPPORTED if (Preferences::emailClient() == Preferences::sendmail && Preferences::emailCopyToKMail()) { // Create a copy of the sent email in KMail's 'sent-mail' folder, // or if there was a send error, in KMail's 'outbox' folder. QString err = addToKMailFolder(jobdata, (fail ? "outbox" : "sent-mail"), true); if (!err.isNull()) { kWarning() << "Error copying to KMail:" << err; errmsgs << errors(err, COPY_ERROR); // not a fatal error - continue if (!fail) copyerr = true; } } #endif if (jobdata.allowNotify) notifyQueued(jobdata.event); theApp()->emailSent(jobdata, errmsgs, copyerr); if (!mJobs.isEmpty()) { // Send the next queued email connect(mJobs.head(), SIGNAL(result(KJob*)), instance(), SLOT(slotEmailSent(KJob*))); mJobs.head()->start(); } } #ifdef KMAIL_SUPPORTED /****************************************************************************** * Add the message to a KMail folder. * Reply = reason for failure (which may be the empty string) * = null string if success. */ QString KAMail::addToKMailFolder(JobData& data, const char* folder, bool checkKmailRunning) { QString err; if (checkKmailRunning) err = KAlarm::runKMail(true); if (err.isNull()) { KMime::Message message; initHeaders(message, data); err = appendBodyAttachments(message, data); if (!err.isNull()) return err; // Write to a temporary file for feeding to KMail KTemporaryFile tmpFile; if (!tmpFile.open()) { kError() << folder << ": Unable to open a temporary mail file"; return QString(""); } tmpFile.setTextModeEnabled(true); tmpFile.write(message.encodedContent()); if (tmpFile.error() != QFile::NoError) { kError() << folder << ": Error" << tmpFile.errorString() << " writing to temporary mail file"; tmpFile.close(); return QString(""); } tmpFile.close(); // Notify KMail of the message in the temporary file org::kde::kmail::kmail kmail(KMAIL_DBUS_SERVICE, KMAIL_DBUS_PATH, QDBusConnection::sessionBus()); QDBusReply reply = kmail.dbusAddMessage(QString::fromLatin1(folder), tmpFile.fileName(), QString()); if (!reply.isValid()) kError() << "D-Bus call failed:" << reply.error().message(); else if (reply.value() <= 0) kError() << "D-Bus call returned error code =" << reply.value(); else return QString(); // success err = i18nc("@info", "Error calling KMail"); } kError() << folder << ":" << err; return err; } #endif // KMAIL_SUPPORTED /****************************************************************************** * Create the headers part of the email. */ void initHeaders(KMime::Message& message, KAMail::JobData& data) { KMime::Headers::Date* date = new KMime::Headers::Date; date->setDateTime(KDateTime::currentDateTime(Preferences::timeZone())); message.setHeader(date); KMime::Headers::From* from = new KMime::Headers::From; from->fromUnicodeString(data.from, autoDetectCharset(data.from)); message.setHeader(from); KMime::Headers::To* to = new KMime::Headers::To; EmailAddressList toList = data.event.emailAddresses(); for (int i = 0, count = toList.count(); i < count; ++i) to->addAddress(toList[i].email().toLatin1(), toList[i].name()); message.setHeader(to); if (!data.bcc.isEmpty()) { KMime::Headers::Bcc* bcc = new KMime::Headers::Bcc; bcc->fromUnicodeString(data.bcc, autoDetectCharset(data.bcc)); message.setHeader(bcc); } KMime::Headers::Subject* subject = new KMime::Headers::Subject; QString str = data.event.emailSubject(); subject->fromUnicodeString(str, autoDetectCharset(str)); message.setHeader(subject); KMime::Headers::UserAgent* agent = new KMime::Headers::UserAgent; agent->fromUnicodeString(KGlobal::mainComponent().aboutData()->programName() + "/" KALARM_VERSION, "us-ascii"); message.setHeader(agent); KMime::Headers::MessageID* id = new KMime::Headers::MessageID; id->generate(data.from.mid(data.from.indexOf('@') + 1).toLatin1()); message.setHeader(id); } /****************************************************************************** * Append the body and attachments to the email text. * Reply = reason for error * = empty string if successful. */ QString KAMail::appendBodyAttachments(KMime::Message& message, JobData& data) { QStringList attachments = data.event.emailAttachments(); if (!attachments.count()) { // There are no attachments, so simply append the message body message.contentType()->setMimeType("text/plain"); message.contentType()->setCharset("utf-8"); message.fromUnicodeString(data.event.message()); message.assemble(); } else { // There are attachments, so the message must be in MIME format message.contentType()->setMimeType("multipart/mixed"); message.contentType()->setBoundary(KMime::multiPartBoundary()); if (!data.event.message().isEmpty()) { // There is a message body KMime::Content* content = new KMime::Content(); content->contentType()->setMimeType("text/plain"); content->contentType()->setCharset("utf-8"); content->fromUnicodeString(data.event.message()); content->assemble(); message.addContent(content); } // Append each attachment in turn for (QStringList::Iterator at = attachments.begin(); at != attachments.end(); ++at) { QString attachment = (*at).toLocal8Bit(); KUrl url(attachment); QString attachError = i18nc("@info", "Error attaching file: %1", attachment); url.cleanPath(); KIO::UDSEntry uds; if (!KIO::NetAccess::stat(url, uds, MainWindow::mainMainWindow())) { kError() << "Not found:" << attachment; return i18nc("@info", "Attachment not found: %1", attachment); } KFileItem fi(uds, url); if (fi.isDir() || !fi.isReadable()) { kError() << "Not file/not readable:" << attachment; return attachError; } // Read the file contents QString tmpFile; if (!KIO::NetAccess::download(url, tmpFile, MainWindow::mainMainWindow())) { kError() << "Load failure:" << attachment; return attachError; } QFile file(tmpFile); if (!file.open(QIODevice::ReadOnly)) { kDebug() << "tmp load error:" << attachment; return attachError; } qint64 size = file.size(); QByteArray contents = file.readAll(); file.close(); bool atterror = false; if (contents.size() < size) { kDebug() << "Read error:" << attachment; atterror = true; } QByteArray coded = KCodecs::base64Encode(contents, true); KMime::Content* content = new KMime::Content(); content = new KMime::Content(); content->setBody(coded + "\n\n"); // Set the content type KMimeType::Ptr type = KMimeType::findByUrl(url); KMime::Headers::ContentType* ctype = new KMime::Headers::ContentType(content); ctype->fromUnicodeString(type->name(), autoDetectCharset(type->name())); ctype->setName(attachment, "local"); content->setHeader(ctype); // Set the encoding KMime::Headers::ContentTransferEncoding* cte = new KMime::Headers::ContentTransferEncoding(content); cte->setEncoding(KMime::Headers::CEbase64); cte->setDecoded(false); content->setHeader(cte); content->assemble(); message.addContent(content); if (atterror) return attachError; } message.assemble(); } return QString(); } /****************************************************************************** * If any of the destination email addresses are non-local, display a * notification message saying that an email has been queued for sending. */ void KAMail::notifyQueued(const KAEvent& event) { KMime::Types::Address addr; QString localhost = QLatin1String("localhost"); QString hostname = KNetwork::KResolver::localHostName(); const EmailAddressList& addresses = event.emailAddresses(); for (int i = 0, end = addresses.count(); i < end; ++i) { QByteArray email = addresses[i].email().toLocal8Bit(); const char* em = email; if (!email.isEmpty() && HeaderParsing::parseAddress(em, em + email.length(), addr)) { QString domain = addr.mailboxList.first().addrSpec().domain; if (!domain.isEmpty() && domain != localhost && domain != hostname) { KMessageBox::information(0, i18nc("@info", "An email has been queued to be sent"), QString(), Preferences::EMAIL_QUEUED_NOTIFY); return; } } } } /****************************************************************************** * Fetch the user's email address configured in the KDE System Settings. */ QString KAMail::controlCentreAddress() { KEMailSettings e; return e.getSetting(KEMailSettings::EmailAddress); } /****************************************************************************** * Parse a list of email addresses, optionally containing display names, * entered by the user. * Reply = the invalid item if error, else empty string. */ QString KAMail::convertAddresses(const QString& items, EmailAddressList& list) { list.clear(); QString invalidItem; const KMime::Types::Mailbox::List mailboxes = parseAddresses(items, invalidItem); if (!invalidItem.isEmpty()) return invalidItem; for (int i = 0, count = mailboxes.count(); i < count; ++i) list += KCal::Person(mailboxes[i].name(), mailboxes[i].addrSpec().asString()); return QString(); } /****************************************************************************** * Check the validity of an email address. * Because internal email addresses don't have to abide by the usual internet * email address rules, only some basic checks are made. * Reply = 1 if alright, 0 if empty, -1 if error. */ int KAMail::checkAddress(QString& address) { address = address.trimmed(); // Check that there are no list separator characters present if (address.indexOf(QLatin1Char(',')) >= 0 || address.indexOf(QLatin1Char(';')) >= 0) return -1; int n = address.length(); if (!n) return 0; int start = 0; int end = n - 1; if (address[end] == QLatin1Char('>')) { // The email address is in <...> if ((start = address.indexOf(QLatin1Char('<'))) < 0) return -1; ++start; --end; } int i = address.indexOf(QLatin1Char('@'), start); if (i >= 0) { if (i == start || i == end) // check @ isn't the first or last character // || address.indexOf(QLatin1Char('@'), i + 1) >= 0) // check for multiple @ characters return -1; } /* else { // Allow the @ character to be missing if it's a local user if (!getpwnam(address.mid(start, end - start + 1).toLocal8Bit())) return false; } for (int i = start; i <= end; ++i) { char ch = address[i].toLatin1(); if (ch == '.' || ch == '@' || ch == '-' || ch == '_' || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) continue; return false; }*/ return 1; } /****************************************************************************** * Convert a comma or semicolon delimited list of attachments into a * QStringList. The items are checked for validity. * Reply = the invalid item if error, else empty string. */ QString KAMail::convertAttachments(const QString& items, QStringList& list) { KUrl url; list.clear(); int length = items.length(); for (int next = 0; next < length; ) { // Find the first delimiter character (, or ;) int i = items.indexOf(QLatin1Char(','), next); if (i < 0) i = items.length(); int sc = items.indexOf(QLatin1Char(';'), next); if (sc < 0) sc = items.length(); if (sc < i) i = sc; QString item = items.mid(next, i - next).trimmed(); switch (checkAttachment(item)) { case 1: list += item; break; case 0: break; // empty attachment name case -1: default: return item; // error } next = i + 1; } return QString(); } /****************************************************************************** * Check for the existence of the attachment file. * If non-null, '*url' receives the KUrl of the attachment. * Reply = 1 if attachment exists * = 0 if null name * = -1 if doesn't exist. */ int KAMail::checkAttachment(QString& attachment, KUrl* url) { attachment = attachment.trimmed(); if (attachment.isEmpty()) { if (url) *url = KUrl(); return 0; } // Check that the file exists KUrl u(attachment); u.cleanPath(); if (url) *url = u; return checkAttachment(u) ? 1 : -1; } /****************************************************************************** * Check for the existence of the attachment file. */ bool KAMail::checkAttachment(const KUrl& url) { KIO::UDSEntry uds; if (!KIO::NetAccess::stat(url, uds, MainWindow::mainMainWindow())) return false; // doesn't exist KFileItem fi(uds, url); if (fi.isDir() || !fi.isReadable()) return false; return true; } /****************************************************************************** * Set the appropriate error messages for a given error string. */ QStringList KAMail::errors(const QString& err, ErrType prefix) { QString error1; switch (prefix) { case SEND_FAIL: error1 = i18nc("@info", "Failed to send email"); break; case SEND_ERROR: error1 = i18nc("@info", "Error sending email"); break; case COPY_ERROR: error1 = i18nc("@info", "Error copying sent email to KMail %1 folder", i18n_sent_mail()); break; } if (err.isEmpty()) return QStringList(error1); QStringList errs(QString::fromLatin1("%1:").arg(error1)); errs += err; return errs; } #ifdef KMAIL_SUPPORTED /****************************************************************************** * Get the body of an email from KMail, given its serial number. */ QString KAMail::getMailBody(quint32 serialNumber) { QList args; args << serialNumber << (int)0; #ifdef __GNUC__ #warning Set correct DBus interface/object for kmail #endif QDBusInterface iface(KMAIL_DBUS_SERVICE, QString(), QLatin1String("KMailIface")); QDBusReply reply = iface.callWithArgumentList(QDBus::Block, QLatin1String("getDecodedBodyPart"), args); if (!reply.isValid()) { kError() << "D-Bus call failed:" << reply.error().message(); return QString(); } return reply.value(); } #endif //----------------------------------------------------------------------------- // Based on KMail KMMsgBase::autoDetectCharset(). QByteArray autoDetectCharset(const QString& text) { static QList charsets; if (charsets.isEmpty()) charsets << "us-ascii" << "iso-8859-1" << "locale" << "utf-8"; for (int i = 0, count = charsets.count(); i < count; ++i) { QByteArray encoding = charsets[i]; if (encoding == "locale") { encoding = QTextCodec::codecForName(KGlobal::locale()->encoding())->name(); kAsciiToLower(encoding.data()); } if (text.isEmpty()) return encoding; if (encoding == "us-ascii") { if (KMime::isUsAscii(text)) return encoding; } else { const QTextCodec *codec = codecForName(encoding); if (!codec) kDebug() <<"Auto-Charset: Something is wrong and I can not get a codec. [" << encoding <<"]"; else { if (codec->canEncode(text)) return encoding; } } } return 0; } //----------------------------------------------------------------------------- // Based on KMail KMMsgBase::codecForName(). const QTextCodec* codecForName(const QByteArray& str) { if (str.isEmpty()) return 0; QByteArray codec = str; kAsciiToLower(codec.data()); return KGlobal::charsets()->codecForName(codec); } /****************************************************************************** * Parse a string containing multiple addresses, separated by comma or semicolon, * while retaining Unicode name parts. * Note that this only needs to parse strings input into KAlarm, so it only * needs to accept the common syntax for email addresses, not obsolete syntax. */ KMime::Types::Mailbox::List parseAddresses(const QString& text, QString& invalidItem) { KMime::Types::Mailbox::List list; int state = 0; int start = 0; // start of this item int endName = 0; // character after end of name int startAddr = 0; // start of address int endAddr = 0; // character after end of address char lastch = '\0'; bool ended = false; // found the end of the item for (int i = 0, count = text.length(); i <= count; ++i) { if (i == count) ended = true; else { char ch = text[i].toLatin1(); switch (state) { case 0: // looking for start of item if (ch == ' ' || ch == '\t') continue; start = i; state = (ch == '"') ? 10 : 1; break; case 1: // looking for start of address, or end of item switch (ch) { case '<': startAddr = i + 1; state = 2; break; case ',': case ';': ended = true; break; case ' ': break; default: endName = i + 1; break; } break; case 2: // looking for '>' at end of address if (ch == '>') { endAddr = i; state = 3; } break; case 3: // looking for item separator if (ch == ',' || ch == ';') ended = true; else if (ch != ' ') { invalidItem = text.mid(start); return KMime::Types::Mailbox::List(); } break; case 10: // looking for closing quote if (ch == '"' && lastch != '\\') { ++start; // remove opening quote from name endName = i; state = 11; } lastch = ch; break; case 11: // looking for '<' if (ch == '<') { startAddr = i + 1; state = 2; } break; } } if (ended) { // Found the end of the item - add it to the list if (!startAddr) { startAddr = start; endAddr = endName; endName = 0; } QString addr = text.mid(startAddr, endAddr - startAddr); KMime::Types::Mailbox mbox; mbox.fromUnicodeString(addr); if (mbox.address().isEmpty()) { invalidItem = text.mid(start, endAddr - start); return KMime::Types::Mailbox::List(); } if (endName) { int len = endName - start; QString name = text.mid(start, endName - start); if (name[0] == '"' && name[len - 1] == '"') name = name.mid(1, len - 2); mbox.setName(name); } list.append(mbox); endName = startAddr = endAddr = 0; start = i + 1; state = 0; ended = false; } } return list; } /*============================================================================= = HeaderParsing : modified and additional functions. = The following functions are modified from, or additional to, those in = libkmime kmime_header_parsing.cpp. =============================================================================*/ namespace HeaderParsing { using namespace KMime; using namespace KMime::Types; using namespace KMime::HeaderParsing; /****************************************************************************** * New function. * Allow a local user name to be specified as an email address. */ bool parseUserName( const char* & scursor, const char * const send, QString & result, bool isCRLF ) { QString maybeLocalPart; QString tmp; if ( scursor != send ) { // first, eat any whitespace eatCFWS( scursor, send, isCRLF ); char ch = *scursor++; switch ( ch ) { case '.': // dot case '@': case '"': // quoted-string return false; default: // atom scursor--; // re-set scursor to point to ch again tmp.clear(); if ( parseAtom( scursor, send, result, false /* no 8bit */ ) ) { if (getpwnam(result.toLocal8Bit())) return true; } return false; // parseAtom can only fail if the first char is non-atext. } } return false; } /****************************************************************************** * Modified function. * Allow a local user name to be specified as an email address, and reinstate * the original scursor on error return. */ bool parseAddress( const char* & scursor, const char * const send, Address & result, bool isCRLF ) { // address := mailbox / group eatCFWS( scursor, send, isCRLF ); if ( scursor == send ) return false; // first try if it's a single mailbox: Mailbox maybeMailbox; const char * oldscursor = scursor; if ( parseMailbox( scursor, send, maybeMailbox, isCRLF ) ) { // yes, it is: result.displayName.clear(); result.mailboxList.append( maybeMailbox ); return true; } scursor = oldscursor; // KAlarm: Allow a local user name to be specified // no, it's not a single mailbox. Try if it's a local user name: QString maybeUserName; if ( parseUserName( scursor, send, maybeUserName, isCRLF ) ) { // yes, it is: maybeMailbox.setName( QString() ); AddrSpec addrSpec; addrSpec.localPart = maybeUserName; addrSpec.domain.clear(); maybeMailbox.setAddress( addrSpec ); result.displayName.clear(); result.mailboxList.append( maybeMailbox ); return true; } scursor = oldscursor; Address maybeAddress; // no, it's not a single mailbox. Try if it's a group: if ( !parseGroup( scursor, send, maybeAddress, isCRLF ) ) { scursor = oldscursor; // KAlarm: reinstate original scursor on error return return false; } result = maybeAddress; return true; } } // namespace HeaderParsing