Exemplo n.º 1
0
Message& Message::reset() noexcept {
  return clear_headers().clear_body();
}
Exemplo n.º 2
0
int local_scan(int fd, uschar **return_text)
    {
    PyObject *user_dict;
    PyObject *user_func;
    PyObject *result;
    PyObject *header_tuple;
    PyObject *original_recipients;
    PyObject *working_recipients;

    if (!expy_enabled)
        return LOCAL_SCAN_ACCEPT;

    if (!Py_IsInitialized())  /* local_scan() may have already been run */
        {
        Py_Initialize();
        ExPy_Header_Line.ob_type = &PyType_Type;
        }

    if (!expy_exim_dict)
        {
        PyObject *module = Py_InitModule(expy_exim_module, expy_exim_methods); /* Borrowed reference */
        Py_INCREF(module);                                 /* convert to New reference */
        expy_exim_dict = PyModule_GetDict(module);         /* Borrowed reference */
        Py_INCREF(expy_exim_dict);                         /* convert to New reference */
        }

    if (!expy_user_module)
        {
        if (expy_path_add)
            {
            PyObject *sys_module;
            PyObject *sys_dict;
            PyObject *sys_path;
            PyObject *add_value;

            sys_module = PyImport_ImportModule("sys");  /* New Reference */
            if (!sys_module)
                {
                PyErr_Clear();
                *return_text = "Internal error, can't import Python sys module";
                log_write(0, LOG_REJECT, "Couldn't import Python 'sys' module"); 
                /* FIXME: write out an exception traceback if possible to Exim log */
                return PYTHON_FAILURE_RETURN;
                }

            sys_dict = PyModule_GetDict(sys_module);               /* Borrowed Reference, never fails */
            sys_path = PyMapping_GetItemString(sys_dict, "path");  /* New reference */

            if (!sys_path || (!PyList_Check(sys_path)))
                {
                PyErr_Clear();  /* in case sys_path was NULL, harmless otherwise */
                *return_text = "Internal error, sys.path doesn't exist or isn't a list";
                log_write(0, LOG_REJECT, "expy: Python sys.path doesn't exist or isn't a list"); 
                /* FIXME: write out an exception traceback if possible to Exim log */
                return PYTHON_FAILURE_RETURN;
                }

            add_value = PyString_FromString(expy_path_add);  /* New reference */
            if (!add_value)
                {
                PyErr_Clear();
                log_write(0, LOG_PANIC, "expy: Failed to create Python string from [%s]", expy_path_add); 
                return PYTHON_FAILURE_RETURN;
                }

            if (PyList_Append(sys_path, add_value))
                {
                PyErr_Clear();
                log_write(0, LOG_PANIC, "expy: Failed to append [%s] to Python sys.path", expy_path_add);                
                }

            Py_DECREF(add_value);
            Py_DECREF(sys_path);
            Py_DECREF(sys_module);
            }

        expy_user_module = PyImport_ImportModule(expy_scan_module);  /* New Reference */

        if (!expy_user_module)
            {
            PyErr_Clear();
            *return_text = "Internal error, can't import Python local_scan module";
            log_write(0, LOG_REJECT, "Couldn't import Python '%s' module", expy_scan_module); 
            return PYTHON_FAILURE_RETURN;
            }
        }

    user_dict = PyModule_GetDict(expy_user_module);                      /* Borrowed Reference, never fails */
    user_func = PyMapping_GetItemString(user_dict, expy_scan_function);  /* New reference */

    if (!user_func)
        {
        PyErr_Clear();
        *return_text = "Internal error, module doesn't have local_scan function";
        log_write(0, LOG_REJECT, "Python %s module doesn't have a %s function", expy_scan_module, expy_scan_function); 
        return PYTHON_FAILURE_RETURN;
        }

    /* so far so good, prepare to run function */

    /* Copy exim variables */
    expy_dict_int("debug_selector", debug_selector);
    expy_dict_int("host_checking", host_checking);
    expy_dict_string("interface_address", interface_address);
    expy_dict_int("interface_port", interface_port);
    expy_dict_string("message_id", message_id);
    expy_dict_string("received_protocol", received_protocol);
    expy_dict_string("sender_address", sender_address);
    expy_dict_string("sender_host_address", sender_host_address);
    expy_dict_string("sender_host_authenticated", sender_host_authenticated);
    expy_dict_string("sender_host_name", sender_host_name);
    expy_dict_int("sender_host_port", sender_host_port);
    expy_dict_int("fd", fd);

    /* copy some constants */
    expy_dict_int("LOG_MAIN", LOG_MAIN);
    expy_dict_int("LOG_PANIC", LOG_PANIC);
    expy_dict_int("LOG_REJECT", LOG_REJECT);
    
    expy_dict_int("LOCAL_SCAN_ACCEPT", LOCAL_SCAN_ACCEPT);
    expy_dict_int("LOCAL_SCAN_ACCEPT_FREEZE", LOCAL_SCAN_ACCEPT_FREEZE);
    expy_dict_int("LOCAL_SCAN_ACCEPT_QUEUE", LOCAL_SCAN_ACCEPT_QUEUE);
    expy_dict_int("LOCAL_SCAN_REJECT", LOCAL_SCAN_REJECT);
    expy_dict_int("LOCAL_SCAN_REJECT_NOLOGHDR", LOCAL_SCAN_REJECT_NOLOGHDR);
    expy_dict_int("LOCAL_SCAN_TEMPREJECT", LOCAL_SCAN_TEMPREJECT);
    expy_dict_int("LOCAL_SCAN_TEMPREJECT_NOLOGHDR", LOCAL_SCAN_TEMPREJECT_NOLOGHDR);
    expy_dict_int("MESSAGE_ID_LENGTH", MESSAGE_ID_LENGTH);
    expy_dict_int("SPOOL_DATA_START_OFFSET", SPOOL_DATA_START_OFFSET);

    expy_dict_int("D_v", D_v);
    expy_dict_int("D_local_scan", D_local_scan);

    /* set the headers */
    header_tuple = get_headers();
    PyDict_SetItemString(expy_exim_dict, "headers", header_tuple);

    /* 
     * make list of recipients, give module a copy to work with in 
     * List format, but keep original tuple to compare against later
     */
    original_recipients = get_recipients();                     /* New reference */
    working_recipients = PySequence_List(original_recipients);  /* New reference */
    PyDict_SetItemString(expy_exim_dict, "recipients", working_recipients);
    Py_DECREF(working_recipients);    

    /* Try calling our function */
    result = PyObject_CallFunction(user_func, NULL);            /* New reference */

    Py_DECREF(user_func);  /* Don't need ref to function anymore */      

    /* Check for Python exception */
    if (!result)
        {
        PyErr_Clear();
        *return_text = "Internal error, local_scan function failed";
        Py_DECREF(original_recipients);
        clear_headers(header_tuple);
        Py_DECREF(header_tuple);
        return PYTHON_FAILURE_RETURN;

        // FIXME: should write exception to exim log somehow
        }

    /* User code may have replaced recipient list, so re-get ref */
    working_recipients = PyDict_GetItemString(expy_exim_dict, "recipients"); /* Borrowed reference */
    Py_XINCREF(working_recipients);                                           /* convert to New reference */

    /* 
     * reconcile original recipient list with what's present after 
     * Python code is done 
     */
    if ((!working_recipients) || (!PySequence_Check(working_recipients)) || (PySequence_Size(working_recipients) == 0))
        /* Python code either deleted exim.recipients alltogether, or replaced 
           it with a non-list, or emptied out the list */
        recipients_count = 0;
    else
        {        
        int i;

        /* remove original recipients not on the working list, reverse order important! */
        for (i = recipients_count - 1; i >= 0; i--)
            {
            PyObject *addr = PyTuple_GET_ITEM(original_recipients, i); /* borrowed ref */
            if (!PySequence_Contains(working_recipients, addr))
                expy_remove_recipient(i);
            }

        /* add new recipients not in the original list */
        for (i = PySequence_Size(working_recipients) - 1; i >= 0; i--)
            {
            PyObject *addr = PySequence_GetItem(working_recipients, i);
            if (!PySequence_Contains(original_recipients, addr))
                receive_add_recipient(PyString_AsString(addr), -1);
            Py_DECREF(addr);
            }
        }

    Py_XDECREF(working_recipients);   /* No longer needed */
    Py_DECREF(original_recipients);   /* No longer needed */

    clear_headers(header_tuple);
    Py_DECREF(header_tuple);          /* No longer needed */

    /* Deal with the return value, first see if python returned a non-empty sequence */
    if (PySequence_Check(result) && (PySequence_Size(result) > 0))
        {
        /* save first item */
        PyObject *rc = PySequence_GetItem(result, 0);

        /* if more than one item, convert 2nd item to string and use as return text */
        if (PySequence_Size(result) > 1)
            {
            PyObject *str;
            PyObject *obj = PySequence_GetItem(result, 1);   /* New reference */
            str = PyObject_Str(obj);                         /* New reference */

            *return_text = string_copy(PyString_AsString(str));

            Py_DECREF(obj);
            Py_DECREF(str);
            }

        /* drop the sequence, and focus on the first item we saved */
        Py_DECREF(result);
        result = rc;
        }

    /* If we have an integer, return that to Exim */
    if (PyInt_Check(result))
        {
        int rc = PyInt_AsLong(result);
        Py_DECREF(result);
        return rc;
        }

    /* didn't return anything usable */
    Py_DECREF(result);
    *return_text = "Internal error, bad return code";
    log_write(0, LOG_REJECT, "Python %s.%s function didn't return integer", expy_scan_module, expy_scan_function); 
    return PYTHON_FAILURE_RETURN;
    }