diff --git a/privatemsg_groups/README b/privatemsg_groups/README
new file mode 100644
index 0000000..3e8c40c
--- /dev/null
+++ b/privatemsg_groups/README
@@ -0,0 +1,5 @@
+Must be enabled at least "write privatemsg to own groups" to be able to send messages.
+
+By default, activating the option before, all the users that belong to a group are able to send messages to group, to restrict this settings only to administrator, please go to "admin/settings/messages" and check "Restrict access to group administrators" option.
+
+Author: paolomainardi@gmail.com (http://drupal.org/user/302937)
diff --git a/privatemsg_groups/privatemsg_groups.info b/privatemsg_groups/privatemsg_groups.info
new file mode 100644
index 0000000..bb56b30
--- /dev/null
+++ b/privatemsg_groups/privatemsg_groups.info
@@ -0,0 +1,8 @@
+name = Privatemsg Groups
+description = Allows to send message to all members of a group.
+package = Mail
+core = 6.x
+dependencies[] = privatemsg
+dependencies[] = og
+
+
diff --git a/privatemsg_groups/privatemsg_groups.module b/privatemsg_groups/privatemsg_groups.module
new file mode 100644
index 0000000..4c451d4
--- /dev/null
+++ b/privatemsg_groups/privatemsg_groups.module
@@ -0,0 +1,206 @@
+<?php
+
+/**
+ * @file
+ * Allows to send messages to all members of a group.
+ */
+
+/**
+ * Implements hook_perm().
+ */
+function privatemsg_groups_perm() {
+  $perms = array('write privatemsg to all groups', 'write privatemsg to own groups');
+  return $perms;
+}
+
+
+/**
+ * Implements hook_theme().
+ */
+function privatemsg_groups_theme() {
+  return array(
+    'privatemsg_groups_format' => array(
+      'arguments' => array('group' => NULL, 'options' => array()),
+    ),
+  );
+}
+
+/**
+ * Implements hook_privatemsg_recipient_types_info().
+ */
+function privatemsg_groups_privatemsg_recipient_type_info() {
+  return array(
+    'group' => array(
+      'name' => t('Group'),
+      'description' => t('Enter the name of a group to write a message to all users that are suscribed to.'),
+      'load' => 'privatemsg_groups_load_multiple',
+      'format' => 'privatemsg_groups_format',
+      'autocomplete' => 'privatemsg_groups_autocomplete',
+      'generate recipients' => 'privatemsg_groups_load_recipients',
+      'count' => 'privatemsg_groups_count_recipients',
+      'write callback' => 'privatemsg_groups_access',
+      'view callback' => 'privatemsg_groups_access',
+    ),
+  );
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function privatemsg_groups_form_privatemsg_admin_settings_alter(&$form, &$form_state) {
+  $form['groups'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Privatemsg groups'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#weight' => 25,
+  );
+
+  $form['groups']['privatemsg_group_admin_grant'] = array(
+    '#title' => t('Restrict access to group administrators'),
+    '#type'  => 'checkbox',
+    '#default_value' => variable_get('privatemsg_group_admin_grant', 1),
+    '#description' => t("Enabling this setting will restrict message sending only to group administrator."),
+    '#weight' => -4,
+  );
+}
+
+/**
+ * Permission check for group recipients.
+ */
+function privatemsg_groups_access($recipient) {
+  global $user;
+  
+  // Check if user has permission to write to all groups.
+  if (user_access('write privatemsg to all groups')) {
+    return TRUE;
+  }
+
+  // Check if user has permission to write to own groups.
+  if (!user_access('write privatemsg to own groups')) {
+    return FALSE;
+  }
+
+  if ($recipient) {
+    // extract group nid from recipient, check if is an object or the nid passed by autocomplete function
+    $nid = (is_object($recipient) ? $recipient->recipient : $recipient);
+
+    // if access is restricted to group admins
+    if (variable_get('privatemsg_group_admin_grant', FALSE)) {
+      return og_is_group_admin($nid);
+    }
+    
+    return og_is_group_member($nid);
+  }
+
+  // give access only to users that have group subscriptions
+  return (bool) (count(og_get_subscriptions($user->uid)));
+}
+
+/**
+ * Load a number of groups based on their nid.
+ */
+function privatemsg_groups_load_multiple($nids) {
+  $result = db_query("SELECT n.title, n.nid AS recipient FROM {node} n JOIN {og} ON n.nid = og.nid WHERE n.status = 1 AND n.nid IN (" . db_placeholders($nids) . ")", $nids);
+  $groups = array();
+  while ($group = db_fetch_object($result)) {
+    $group->type = 'group';
+    $groups[privatemsg_recipient_key($group)] = $group;
+  }
+  
+  return $groups;
+}
+
+/**
+ * Format a group to be displayed as a recipient.
+ */
+function theme_privatemsg_groups_format($group, $options = array()) {
+  if (!empty($options['plain'])) {
+    $name = $group->title;
+    if (!empty($options['unique'])) {
+      $name .= ' [group]';
+    }
+    return $name.'(group)';
+  }
+  return t('%group (group)', array('%group' => $group->title));
+}
+
+/**
+ * Loads users of a specific group.
+ */
+function privatemsg_groups_load_recipients($recipient, $limit, $offset) {
+  $recipients = array();
+  $nid = isset($recipient->recipient) ? $recipient->recipient : $recipient->nid;
+  $result = db_query(og_list_users_sql(1, 0, null, false), $nid);
+  while ($row = db_fetch_object($result)) {
+    $recipients[] = $row->uid;
+  }
+  return $recipients;
+}
+
+/**
+ * Return the number of users which have a given group.
+ */
+function privatemsg_groups_count_recipients($recipient) {
+  $nid = isset($recipient->recipient) ? $recipient->recipient : $recipient->nid;
+  return db_result(db_query(og_list_users_sql(1, 0, null, true), $nid));
+}
+
+/**
+ * Provides autocomplete suggestions for groups.
+ */
+function privatemsg_groups_autocomplete($fragment, $names, $limit) {
+  $query = _privatemsg_assemble_query(array('autocomplete_groups', 'privatemsg_groups'), $fragment, $names);
+  $result = db_query_range($query['query'], $fragment, 0, $limit);
+  // 3: Build proper suggestions and print.
+  $groups = array();
+  while ($group = db_fetch_object($result)) {
+    if (user_access('write privatemsg to all groups') || (privatemsg_groups_access($group->nid))) {
+      $group->type = 'group';
+      $group->recipient = $group->nid;
+      $groups[privatemsg_recipient_key($group)] = $group;
+    }
+  }
+  return $groups;
+}
+
+/**
+ * Implements hook_privatemsg_name_lookup().
+ */
+function privatemsg_groups_privatemsg_name_lookup($string) {
+  // Remove optonal group specifier.
+  $string = trim(str_replace(array(t('[group]'), '(group)'), '', $string));
+  $result = db_query("SELECT n.*, n.nid AS recipient FROM {node} n JOIN {og} ON og.nid = n.nid WHERE n.title = '%s' AND n.status = 1", trim($string));
+  if ($group = db_fetch_object($result)) {
+    $group->type = 'group';
+    return array(privatemsg_recipient_key($group) => $group);
+  }
+}
+
+/**
+ * Query definition to search for username autocomplete suggestions.
+ *
+ * @param $fragments
+ *   Query fragments array.
+ * @param $search
+ *   Which search string is currently searched for.
+ * @param $names
+ *   Array of names not to be used as suggestions.
+ */
+function privatemsg_groups_sql_autocomplete_groups(&$fragments, $search, $names) {
+  $fragments['primary_table'] = '{node} n';
+  $fragments['select'][] = 'n.title, n.nid';
+
+  // Escape the % to get it through the placeholder replacement.
+  // Join another table.
+  $fragments['inner_join'][] = 'JOIN {og} og ON (n.nid = og.nid)';
+  $fragments['where'][] = "n.title LIKE '%s' AND n.status = 1";
+  $fragments['query_args']['where'][] = $search .'%%';
+  if (!empty($names)) {
+    // If there are already names selected, exclude them from the suggestions.
+    $fragments['where'][] = "n.title NOT IN (". db_placeholders($names, 'text') .")";
+    $fragments['query_args']['where'] += $names;
+  }
+ 
+  $fragments['order_by'][] = 'n.title ASC';
+}
