diff --git a/Project.toml b/Project.toml index f5bb5ed..4c8e245 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "GMime" uuid = "158299e7-fc4f-4c3e-9fda-ad8bb0e07f1e" -version = "1.0.0" +version = "1.0.1" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" diff --git a/src/GMime.jl b/src/GMime.jl index d727f0e..2b731da 100644 --- a/src/GMime.jl +++ b/src/GMime.jl @@ -137,7 +137,8 @@ export g_mime_filter_basic_new export g_mime_content_encoding_to_string export g_object_unref, - g_date_time_format + g_date_time_format, + g_free export EmailAttachment, Email, @@ -282,7 +283,7 @@ function g_mime_stream_mem_new() end function g_mime_stream_mem_new_with_byte_array(array) - return ccall((:g_mime_stream_mem_new_with_byte_array, libgmime), Ptr{GMimeStream}, (Ptr{Vector{UInt8}},), array) + return ccall((:g_mime_stream_mem_new_with_byte_array, libgmime), Ptr{GMimeStream}, (Ptr{UInt8},), array) end function g_mime_stream_mem_new_with_buffer(buffer, len) @@ -593,6 +594,10 @@ function g_date_time_format(datetime, format) return ccall((:g_date_time_format, libgmime), Ptr{UInt8}, (Ptr{GDateTime}, Ptr{UInt8}), datetime, format) end +function g_free(ptr) + return ccall((:g_free, libgmime), Cvoid, (Ptr{Cvoid},), ptr) +end + include("Parser.jl") using .Parser diff --git a/src/Parser.jl b/src/Parser.jl index 3689d59..c3a0b64 100644 --- a/src/Parser.jl +++ b/src/Parser.jl @@ -7,6 +7,8 @@ export EmailAttachment, using Dates using ..GMime +const DATE_FORMAT = DateFormat("yyyy-mm-dd HH:MM:SS") + struct GMimeError <: Exception message::String end @@ -81,7 +83,9 @@ function extract_addresses(msg::Ptr{GMimeMessage}, addr_type::GMimeAddressType) for i = 0:size-1 addr = internet_address_list_get_address(addr_list, i) - addrs[i+1] = unsafe_string(internet_address_to_string(addr, C_NULL, true)) + addr_ptr = internet_address_to_string(addr, C_NULL, true) + addrs[i+1] = unsafe_string(addr_ptr) + g_free(addr_ptr) end return addrs @@ -89,8 +93,12 @@ end function extract_date(msg::Ptr{GMimeMessage}) date = g_mime_message_get_date(msg) - date_string = unsafe_string(g_date_time_format(date, "%Y-%m-%d %H:%M:%S")) - return DateTime(date_string, DateFormat("yyyy-mm-dd HH:MM:SS")) + date_str_ptr = g_date_time_format(date, "%Y-%m-%d %H:%M:%S") + try + DateTime(unsafe_string(date_str_ptr), DATE_FORMAT) + finally + g_free(date_str_ptr) + end end function read_text_data(part::Ptr{GMimeObject}) @@ -106,8 +114,8 @@ function read_text_data(part::Ptr{GMimeObject}) return content end -function handle_body(::Ptr{GMimeObject}, part::Ptr{GMimeObject}, user_data::Ptr{Vector{UInt8}}) - mime_type = g_mime_object_get_content_type(part) +function handle_body(::Ptr{GMimeObject}, part::Ptr{GMimeObject}, user_data::Ptr{UInt8}) + mime_type = g_mime_object_get_content_type(part) # Skip every objects except email text body (text/plain) g_mime_content_type_is_type(mime_type, "text", "plain") || return nothing @@ -124,8 +132,8 @@ end function extract_text_body(msg::Ptr{GMimeMessage}) text_body = UInt8[] - callback = @cfunction(handle_body, Cvoid, (Ptr{GMimeObject}, Ptr{GMimeObject}, Ptr{Vector{UInt8}})) - text_body_ptr = pointer_from_objref(text_body) + callback = @cfunction(handle_body, Cvoid, (Ptr{GMimeObject}, Ptr{GMimeObject}, Ptr{UInt8})) + text_body_ptr = Ptr{UInt8}(pointer_from_objref(text_body)) g_mime_message_foreach(msg, callback, text_body_ptr) return text_body end @@ -141,7 +149,7 @@ function read_stream_data(stream::Ptr{GMimeStream}, buffer_size::Int64 = 4096) return content end -function handle_attachment(::Ptr{GMimeObject}, part::Ptr{GMimeObject}, user_data::Ptr{Vector{EmailAttachment}}) +function handle_attachment(::Ptr{GMimeObject}, part::Ptr{GMimeObject}, user_data::Ptr{EmailAttachment}) mime_type = g_mime_object_get_content_type(part) # Skip multipart objects and objects that are not attachments @@ -166,27 +174,30 @@ function handle_attachment(::Ptr{GMimeObject}, part::Ptr{GMimeObject}, user_data # Read attachment data g_mime_stream_filter_add(filtered_stream, filter) + g_object_unref(filter) attachment_data = read_stream_data(filtered_stream) + g_object_unref(filtered_stream) # Add attachment to the list encoding_str = unsafe_string(g_mime_content_encoding_to_string(encoding_type)) - mime_type_str = unsafe_string(g_mime_content_type_get_mime_type(mime_type)) + type_str_ptr = g_mime_content_type_get_mime_type(mime_type) attachments_list = unsafe_pointer_to_objref(user_data) - push!(attachments_list, EmailAttachment(filename, encoding_str, mime_type_str, attachment_data)) + push!(attachments_list, EmailAttachment(filename, encoding_str, unsafe_string(type_str_ptr), attachment_data)) + g_free(type_str_ptr) return nothing end function extract_attachments(msg::Ptr{GMimeMessage}) attachments = EmailAttachment[] - callback = @cfunction(handle_attachment, Cvoid, (Ptr{GMimeObject}, Ptr{GMimeObject}, Ptr{Vector{EmailAttachment}})) - attachment_ptr = pointer_from_objref(attachments) + callback = @cfunction(handle_attachment, Cvoid, (Ptr{GMimeObject}, Ptr{GMimeObject}, Ptr{EmailAttachment})) + attachment_ptr = Ptr{EmailAttachment}(pointer_from_objref(attachments)) g_mime_message_foreach(msg, callback, attachment_ptr) return attachments end function stream_init(data::AbstractVector{UInt8}) - stream = g_mime_stream_mem_new_with_buffer(pointer(data), length(data)) + stream = g_mime_stream_mem_new_with_buffer(data, length(data)) stream == C_NULL && throw(GMimeError("Failed to create memory stream.")) return stream end @@ -268,4 +279,6 @@ function parse_email(data::AbstractString) return parse_email(codeunits(data)) end +precompile(push!, (Vector{EmailAttachment}, EmailAttachment)) + end